WordPressをnginxに変えたらデフォルトでメモリ逼迫。php-fpmの調節が必要だった

先週末からこのブログは新サーバーに移行している。
apacheだったHTTPサーバーはnginxに変わった。

前はTwitterに投稿しただけでクローラーが来てパンクするような激悪ブログだったけれども、今回ので少しは改善されたと思うのだが、
公開してしばらくしてfreeコマンドでメモリの使用量を見てみたら、1Gのメモリは使い切っていて、
2GのSWAPはすでに1Gも使っていた。

つまり2GBも使っていた。

軽くて早くて小規模サーバーでもアクセスをバンバンさばくんじゃなかったのか!!と思ったのだが、そこは違った。

nginxとは

nginxとは個人的にはンギンクスと呼んでいるけれど、正式発音はエンジンエックスだ。
apacheの同時アクセス数が増加したときにパフォーマンスが非常に悪くなる現象をどうにかするために開発されたポストapacheなHTTPサーバーだ。

apacheはアクセスがあるとプロセスを立ち上げていく。並行でアクセスを処理していくわけだが、同時アクセスが増えるとプロセス立ち上げも増えていき、メモリが足りなくなってくる。

そこで上限を計算してチューニングをする。

前のVPSはメモリは1GでSWAPも1Gだった。
conoHaVPSはSSDだからSWAP使ってもパフォーマンスそんなに落ちないけれど、前のVPSは激遅になった。
conoHaはSWAPはファイルだけれども、前のVPSはSWAP領域をマウントしていた。
噂でしかなかったのだけれどもそのSWAP領域は他の契約者と共同で使っているから、全体で逼迫するとプロセスがキルされるとも言われていたので、
SWAPに足が入らないように注意してチューニングしていた。

結果、同時アクセス数は20にも満たないようになってしまった。

20以上のアクセスが来ると先に来ていた人たちのアクセスが終わるまで待ちになる。

Twitterでリンク貼り付けると、画像つきのキレイな要約みたいなのがでるとおもうが、あれはTwitterカードと言う仕組みなのだが、あれをすると沢山クローラーが押し寄せてくる。

だからツイートするとアクセスが集中してしまい、ページを開くにも1分とか2分とか待たされることになっていた。

一方nginxは、プロセスを立ち上げないでシングルスレッドで処理をしているそうだ。
アクセスがあるとイベント起動されて処理をする。
高負荷の状態でも使用メモリは肥大化せずにさばくことはできる。

狭い部屋でチケットをもぎるとき、Apacheはバイトを沢山雇ってギュウギュウになってしまうところ、nginxは一人がすごい頑張ってチケットもぎりをしているようなイメージだろうか?

それで早いのかどうなのか

nginxの先のPHP-FPM

nginxは実はそれほど機能は沢山なかった。

ApacheはデフォルトのモジュールでPHPの処理などができるが、
nginxはリクエストに対して、静的ファイルを返すかプロキシしてその先のアプリケーションに渡すかのどちらかしかしない。

つまりHTTPのリクエストのやりくりに特化しているやつだった。

WordPressのPHPはどうするのかというと、PHP-FPMというアプリケーション上で動いている。
これはPHPのFastCGIを実現するアプリだそうだ。
FastCGIというのはCGIなのだけれどもCGIはリクエストが来るたびにプロセスが上がり終わったら終了するという非常に非効率だったところを、キャッシュを持つことによって効率化した仕組みで、それをPHPの実行に使っているソフトウェアだそうだ。

実はこのPHP-FPMのプロセスがデフォルトで50個立ち上がっていたので、カツカツだったのだ。

ps alx | grep php-\.*pool | grep -v grep | awk '{sum+=$8} END {print sum/NR/1000}'

↑このように、実際にどれくらいのメモリをPHP-FPMが使っているのか平均を出してみたところ、
うちの環境では45Mつかっていた。
それが50個あれば、2250MBだ。

freeで調べた数値にほぼ一致する。

50個が最初に立ち上がっているのは困るので、設定を変えることにする。
設定ファイルはこちら
/etc/php-fpm.d/www.conf

pm = dynamic
pm.max_children = 50
pm.start_servers = 10
pm.min_spare_servers = 10
pm.max_spare_servers = 17
pm.max_requests = 500

僕がとりあえず考えた数値はこちら。

1行目はdynamicに設定、動的にプロセスが変えるモード

2行目は最大のプロセス数。
大量にアクセスが来てもSWAP消費してもいいから受け入れはしたいので2GB強は使っても良いことにした。

3行目は起動時のプロセス数。
プロセスを立ち上げたりキルしたりするのも負荷があるので、あまり小さな数にはしなかった

4行目と5行目は暇なときに残っているプロセスの最小値と最大値。
最大値を越えるプロセスは暇になるとキルされていく。
17というのはメモリの70%くらいなら、まあ使っても良いかな程度で考えてみた。

最後の行は、一つのプロセスがこの数値分リクエストを受けたら終了すると言う設定。
メモリリークなどを防ぐものらしい。
なんかわからないけれど肥大化しがちな気がするので、設定を追加してみた。

Apacheと同じなのか?

つまり、裏側はApacheと同じということなのか。
Apacheと同じようにNginxのさきはプロセスは並列で動いてた。
だが少し違うところはある。
静的ファイルつまり画像とかJSファイルとかはNginxがいい感じにアクセスを返してくれている。
Apacheでは全てリクエストのプロセスにふりわけられていただろうが、今回はPHPに関わるところだけ並列になっている。

あと、個人の勘でしかないが、
ApacheよりPHP-FPMは効率が良い気がする。
というのも同じくらいクローラーのアクセスに晒された場合、Apacheのプロセス数は最大まであがってしまったところ、PHP-FPMはほぼ10~15くらいの間になっていて、
プロセスをどんどん増やすと言う場面はあまりみていない。

昨日までは非常にプロセスを少なく設定して運用していたが、リンクをツイートをしても応答時間が伸びたりする現象は認められなかったので、
Apacheよりずっと良くなっている。

とにかくnginxにしてよかった。
本当に良かった。

スポンサードリンク

関連コンテンツ