ときどきWebがタイムアウトする
WebがちゃんとみえてるかどうかZabbixとPingdomで監視をしています。ZabbixはローカルLANからの監視、Pingdomはインタネット側からの監視です。
最近この両者から時折(4〜5回/日)「見えないよー」という報告が上がってくる現象が発生していました。観測できたとしては、
- リクエストタイムアウトしているようだ。
- またはバックエンドからの応答がなく、502エラーを返している。
- 発生時間帯は特定できない。
- 特にアクセスが多い時間帯に発生するわけではない。深夜、早朝でも発生する。
- 発生時間帯にリクエストが集中しているわけではない。
- すぐに回復する。
といった具合。pingdomもzabbixも60秒間隔での監視なので、実際にはもっと頻繁に上記現象が起きているのではないかと。
TCPコネクション回りが怪しいのかと思い、keepaliveあたりとか、sysctl.confあたりのTCPパラメタを変更してみたりしたんですが効果がない。効果はあったかもしれないけれど、上記の現象は相変わらず発生する。
現象が発生する瞬間をとらえる
どうにもよくわからないので、現象が発生した瞬間のApacheの状態をチェックしてみることに。zabbixの監視間隔を15秒程度に短縮。Apacheのstatus画面をリロードしながら、警告メールを待つことに。
現象をとらえたときのstatus画面をみて、一目瞭然。wwwwwがいっぱいです。/server-statusで参照したときのWはSendingReplyの状態。つまり、Apacheはリクエストは受け取ることはできるけれども、返答することができない状態になっている。
結局どういうこと?
つまりはApacheの複数走っているプロセスのうち、どれかがハングアップしているってことです。ある程度ハングアップしたら、自動的にkillされて新しいプロセスが動き出す。それまでの間に受け取ったリクエストはすべて捨てられて、エラーになるか、タイムアウトになるか。
動作しているApacheでは標準ではないモジュールでmod_sedと、mod_security2を使っています。そのあたりでメモリリークでも起こしてるんじゃないかな。
zabbixの履歴をみると、上記現象が起きている時間帯に確かにSendingReplyの数字が跳ね上がっていることが確認できました。
対処
mpm_event_moduleで動作しているのでそのあたりのディレクティブを以下へ調整。
ThreadsPerChild 25 MaxRequestWorkers 400 MaxConnectionsPerChild 2499
子プロセスは2500ほどリクエストを処理したらkillして新しく起動。
それと一つのプロセスで処理できるスレッド数を小さく。
以前は
MaxConnectionsPerChild 0 ThreadsPerChild 50
でした。MaxConnectionPerChildが0ってことは、無制限ですね。
この処置をして二週間経ちますが、上記現象はでなくなりました。