Apache + mod_perl - MaxClients の値に注意

やっちまった……。きっとだれもが通る道。というかとっくに FAQ か。

恥ずかしながら、知らなかったッス。これって mod_ruby でもありうる話だよね?


Apachemod_perl を使用する時は MaxClients 設定に注意!

  1. Apache の MaxClients(子プロセスの最大数) デフォルト設定は 150。
  2. 他のモジュールにも影響されるが、mod_perl 組み込み時、子プロセス1つのメモリサイズが 20〜30MB 程度になる。
  3. よって、同時接続数 150 までアクセスされると 3G から 4.5G メモリを喰うことになる。

そんなメモリねぇ〜www なので、スワップ・スワップ(SWAP x SWAP と書いてみたがヤな感じだった)。swap もオーバーしちゃったり。


対策:

  • MaxClients は「総メモリサイズ / Apache 子プロセス1つのメモリサイズ」(ドンブリ勘定)にする。
  • できれば KeepAlive は Off
    • 1ページで引っこ抜くリソースが多い(画像が多いとか)場合は、画像だけ「pound + 別のウェブサーバー」に任せる、といった構成にする。
    • Off にせずとも MaxKeepAliveRequests, KeepAliveTimeout を調整して改善するかもしれない。
  • Apache モジュールを減らして、子プロセスのメモリサイズを減らす
$ ab -c 100 -n 1000 -k http://example.com/hoge

テスト機で試した。MaxClients 調整前はめっさ重くなる(SSHまで!)。MaxClients 調整後はなんとか耐えられる。


総メモリサイズ は /proc/meminfo からわかるとして、1子プロセスのメモリサイズは ps の出力の VSZ で良いのかな?

$ ps auxww | grep ^www
USER       PID %CPU %MEM   VSZ  RSS TTY      STAT START   TIME COMMAND
www       2783  2.2  2.7 33080 24456 ?       S    11:26   0:02 /usr/local/apache/bin/httpd
...

モジュール入れすぎ!もあるけど、VSZ と RSS じゃ大分変わるんだよなぁ。
404 - エラー: 404

VSZ
プロセスの仮想メモリサイズ (KiB, 1024 バイト単位)。デバイスマッピングは現在のところ除外されているが、これは変更される。 (別名 vsize)。
RSS
常駐セットの大きさ。タスクが使用しているスワップされていない物理メモリ (kB 単位)。 (別名 rssize, rsz)。

わかったような、わからんような説明だな(←わかってない)。


あと、スライドにある Apache の Shared_RAM_per_Child (子プロセスの共有メモリ量)ってどうやってわかるんだろ? むー。


追記:
はてなブックマークの naoya さんのコメントによると、

Shared RAM per Child は RSS - SHARE. 正確に知りたければ GTop を使うと良いです。

とのこと。リモート親切だぁね。


kounoike さんのトラックバックによると、linux カーネル 2.6.11.7 以降は /proc/プロセスID/smaps でわかるらしい。


御二方サンクス!
コメントしてくれた id:lyokato さんもサンクス!


追記2:
WebプログラマのためのCopy On Write解説:mod_perl/FastCGIでメモリを節約する方法 | Typemiss.net
linux では fork(2) の Copy on Write 機能のおかげで、高速 fork&効率的なメモリ共有ができているんだって。"Copy on Write" は「(差異が生じる時の)書き込み時に初めてコピーされる」機能ってとこか。


モジュールも複製されていくのかぁ。勉強になった。