WordPress を使い始めた頃から、とても重くなる事象が出ていた。てっきり、Wordpress の所為だとばっかり考えていたのだが、どうも違うようだ。
現象としては、Apache の process が増え続け、最終的には MaxClients まで達し、そのまま停止。
現象が出る前と、出てからの変更点は
- Serene Bach から WordPress への移行
- Dynamic Contents のアクセスの割合 Perl → PHP へと変化
- DBほとんど利用せず→MySQL の多用
ということになり、PHPとMySQL、ひいては WordPress がいやがらせをしているんだろうと考えました。
ですが。
まず
Apache の Server-Status を見てみると
Server Version: Apache/2.2.3 (Debian) PHP/5.2.0-8+etch13 mod_ssl/2.2.3 OpenSSL/0.9.8c
Server Built: Sep 6 2008 09:52:20
Current Time: Thursday, xx-Yyy-2008 xx:xx:xx JST
Restart Time: Wednesday, xx-Yyy-2008 xx:xx:xx JST
Parent Server Generation: 0
Server uptime: x day xx hour xx minutes xx seconds
xx requests currently being processed, xx idle workers
WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW...........................
................................................................
................................................................
................................................................
Scoreboard Key:
"_" Waiting for Connection, "S" Starting up, "R" Reading Request,
"W" Sending Reply, "K" Keepalive (read), "D" DNS Lookup,
"C" Closing connection, "L" Logging, "G" Gracefully finishing,
"I" Idle cleanup of worker, "." Open slot with no current process
このような感じで、”W” がほとんどとなる現象が発生し、メモリを食い散らかし、挙げ句の果ては Webアクセスが停止となります。
片手間だったので、原因を特定するのにだいぶ手間取りましたが、以下のことが判明しました。
- Apache のエラーログに、MaxClients に達している、とエラーが発生
- 各apache プロセスを lsof すると、CLOSE_WAIT で停止している様子。
- netstat -an すると、大半が CLOSE_WAIT でプロセス完結
ということで、CLOSE_WAIT しているサイトを調査しましたところ、相手が “google” 様であると判明しました。Apache のアクセスログと比較してみると、Googlebot のようです。
要するに、クローラー仕掛けてまくって、通信が中途半端になって、そのまま CLOSE_WAIT させられているケースが多いという状況。
CLOSE_WAIT を短期間に削減するためには、Linux 側の Keepalive timeout を調整するしかありません。当該サーバでは、標準のままで問題がなかったので、そのままにしていましたが、あきらめて変更し、様子を見てみることにしました。
次の項目を変更。
tcp_keepalive_time 7200(sec) –> 180(sec)
tcp_keepalive_probes 9(回) –> 4(回)
tcp_keepalive_intvl 75(sec) –> 5(sec)
今現在、これで問題は出ていない様子です。また、報告します。
ApacheでSending Reply、CLOSE_WAITなプロセスが大量に残る場合に、tcp_keepaliveまわりの設定を変更してる。