apacheのパフォーマンス調整 ( モジュールの削減とprefork MPMの調整 )

apacheのプロセスがメモリリークしつつ増殖

ある案件で、サーバーを移設してから、おそらくphpが発生源と思われるメモリリークを抱えたまま、大量のプロセスが滞留してしまうことにより、メモリを食い散らかしていました。おかげで物理メモリはおろか、swapまで満潮を迎えてMySQLの周辺で血を吐き始める事態に。

正直に申し上げて、そこそこ広大なシステムだった為、メモリリークの箇所の特定が難しく、つーかphpにおけるメモリリーク箇所の探索なんて高尚なスキルが無かった為、apacheの設定を調整することで対処しました。

以下、その記録をば。

prefork MPMを調整

原因はhttpdプロセスの数と、1プロセスあたりのメモリ消費が膨れあがる事。実際は、先輩の助けを借りつつ、サーバーステータスやら前後関係やらを検討しまくって辿りついた答えでした。

本来であれば多少のメモリリークは、寿命の短いphpのことなので、プロセスが短いスパンで再生成されることによりリフレッシュされます。ただ、今回のケースの場合、アクセス数が想定より ( 残念ながら ) 遙かに乏しかったことで、リフレッシュの周期が短くなりメモリが泡を吹いていました。

httpd.confを見る

httpd.confを確認すると、大口の受け入れ体制を敷いている設定。小口設定に変更します。

<IfModule prefork.c>
#--- BEFORE
#StartServers       8     ← サーバー起動時のプロセス数
#MinSpareServers    5 ← プロセスの最小待機数
#MaxSpareServers   20 ← プロセスの最大待機数
#ServerLimit      256 ← MaxClientsと同値でいいらしい(よく分からん)
#MaxClients       256 ← プロセスの最大起動数
#MaxRequestsPerChild  50 ← 1プロセスが死ぬまでに扱えるリクエスト数

#--- AFTER
StartServers        4
MinSpareServers     2
MaxSpareServers    10
ServerLimit       128
MaxClients        128
MaxRequestsPerChild 30
</IfModule>

という感じで、プロセス数を減らし、リフレッシュの周期を早めることで対処しました。もちろん、これで大量のリクエストに対する処理力が落ちるため、アクセス数の成長に合わせて設定を変更する必要があります。

モジュールの読み込みを減らす

あと、少しでもプロセスの単価を下げるためにモリモリ読み込まれていたモジュールの幾つかをコメントアウトしました。どれが要らないものか知識がなかったので、LDAPとかDAVとか系統的なまとまりで調べて、そいつらをまとめて無効化するに留めています。

削除対象

mod_ldap.so
LDAP系モジュールに接続プールやキャッシュを提供
mod_authnz_ldap.so
LDAP認証を提供
mod_dav.so
分散オーサリングとバージョン管理のWebDAV機能を提供
mod_dav_fs.so
WebDAVサービスのファイルシステムプロバイダ
mod_speling.so
誤ったリクエストURLを校正して解決を試みる

以上のモジュールを中心に、明らかにいらない感じのモジュールの読み込みをコメントアウト。

どうでもいいけど、mod_spelingすげーな。でも間違っているなら間違っていることをちゃんと教えてあげたほうがいいような気がする。

参考URL

同時起動しているプロセスの、個体数を減らす&寿命を縮めることで全体的にメモリを節約。ついでにモジュールを減らすことで、個体の単価を下げる。実際のアクセス数に対して、サーバーの設定が見合ってなかったとも言えるかも。まあ、メモリリーク作らなきゃいいって話ですが...。

今回はあまり触ったことがないapacheな話だったので、大分調べないと頭が追いつきませんでした。とはいえ、なんとか良い感じで安定して、はや二ヶ月ぐらい経っているので善きかな。