httpd.confのデフォルト設定では、
MaxClinets 256
ServerLimit 256
になっている。
これは、Apacheが最大256プロセス起動して256コネクションに応答するという設定。
さて、これは適切な設定なのだろうか?
メモリ状況をベースに検討してみる。
Apacheが停止した状態でメモリ状況を確認。
#free
total | used | free | shared | buffers | cached | |
Mem: | 514912 | 376800 | 138112 | 0 | 144052 | 203260 |
-/+ buffers/cache: | 29488 | 485424 | ||||
Swap: | 1048568 | 2852 | 1045716 |
Apacheの1プロセスが消費するメモリを確認。
#ps alx|grep httpd
F UID PID PPID PRI NI VSZ RSS WCHAN STAT TTY TIME COMMAND
5 48 32222 32212 21 0 39112 3872 374588 S ? 0:00 /usr/sbin/httpd
・・・
RSSが実際に使用されているメモリ量で、この場合、3872KB使われていると言うこと。
256プロセスだと、3872KB*256=968MBのメモリを消費するという計算。
空きメモリはいくつあったかというと、freeの結果に、138112KB(134MB)と書かれている。 Linuxでは、bufferとcacheについては必要に応じて切り出して使用できる(と言っても、少し残しておかないと応答が低下するので、全ては使えないが)ので、buffers:144052KB(140MB)とcached:203260KB(198MB)を加えた472MB位まで使える(-/+ buffers/cache:のfree値)わけだが、使えるメモリの2倍ほどを消費してしまうことになる。
使えるメモリをhttpdの消費メモリで除算すると
485424/3872=125
であるから、125プロセスまでが物理メモリに収まると言うことになる。
ServerLimit 256だと、126プロセス目が立ち上がるとスワップが発生し、その応答が遅くなり、処理できないうちに次のリクエストが来ると127プロセス目を立ち上げようとして、処理できずに更に128プロセス・・・となって、プロセスが増え続ける。
すると最終的にシステムが応答不能に陥って見かけ上ダウンする(あるいは、高負荷で実際にダウンする)
故に、MaxClients/ServerLimitを125以下に制限するべきである。
ついでなので、prefork.c設定を解説しておく。
・StartServers
httpd startしたときに起動するプロセスの数。 多くすると初期の起動が遅くなるし、必要に応じてプロセスはServerLimitまで追加されていくので、数個起動しておけば問題ないはずだ。
・MinSpareServers
プロセスの予備数の最低値で、アクセスがない状態ではプロセスを自動終了するけど、この数のプロセスは最低限残しておく。 これが小さいと、急にアクセスが来たときにプロセスを起動する遅延が発生するが、大きいとアクセスがない状態でもメモリを消費し続ける。
・MaxSpareServers
MinSpareServersの逆で、アクセスが集中してプロセスが大量に立ち上がった後に、アクセスが減ると、アクティブな接続がないプロセスはこの数を残して自動終了される。
・MaxRequestsPerChild
一つのプロセスが処理するリクエストの上限を設定する。 この数までリクエストを受け付けたプロセスは終了される。 プロセス内でメモリリークを起こした場合等に一度停止させることでメモリを解放させる効果などがある。
あるPHPプログラムでメモリを消費したときに、Apacheの1プロセスが300MB近いメモリを確保しながら、ページ読み込みが終了しても開放せず、予想外のメモリ消費を起こしてシステムがダウンする事があったので、MaxRequestsPerChildに適当な値を設定しておくことで運用的に暫定対応した事もある。
(222)