ときどき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ってことは、無制限ですね。
この処置をして二週間経ちますが、上記現象はでなくなりました。