プロセスが多くてはメモリ浪費がひどい

朝にBlogにアクセスすると異常に重くて、状況を確認しようとするとSSHアクセスも重い。

MySQLなど一時停止して、再起動すると立て直せたが、いろいろ重くて、

始業前にいろいろ対策をしていた。


これまでBlogではデータベースシステムを使ってなかったんだな。

ところがWordPressを使うのは不可避だとMySQLを導入したら、これがリソースを食ってた。

ただ、MySQLについては負荷軽減のための対策はこれといってなく、

対策をしたのはそれ以外の部分である。


結論から言えば、メモリの消費がひどかったんだよね。

# free

RAMはほぼ全部を食い潰し(メモリの余裕はavailableの数字をみるとよい)、スワップすら半分以上使ってた。

このVPSの契約がメモリ1GBというケチな契約なのがそもそも悪いのだが、

簡単に増量できなさそうだし、少ないメモリ消費でもパフォーマンスを維持できる仕組みを考えることに。

まずは現状分析のためにプロセス毎のリソース消費量を調べた。

# ps aux --sort=-%mem

これでメモリ消費量順に並ぶのだけど、筆頭はmysqldでしたね。

でもmysqldは1つだけなんですよ。

複数のプロセスに分断されてるものを合計して考えると一番ひどかったのはphp-fpmだったんですよね。

あと使ってないのに消費してたという点ではsssdというのがあって、認証関係のデーモンらしいが使ってないのは確実なので無効化した。


php-fpmとはなにかという話だが、これはPHPを使ったことあるひとでもなじみがない人は多いかも。

このサーバーでは以前よりPHPをfastcgiを使って動かしてきた。

FastCGIは本当に速いけど…それだけ?

それがいつしかphp-fpmというもので管理されるのが標準になったらしい。

なんとなく旧来のApacheプラグインとして動くPHPと似てきた気もするけど、あくまでも違うものなのかな。

とはいえ、これが一番良さそうなのは確かなのでphp-fpmを採用している。

ユーザーディレクトリに限ってはこのとき書いたのと同じFCGIWrapperを使う方法にしてるけど。


で、php-fpmは標準設定だと最大50個までプロセスを動的に増やせるらしく、多すぎるプロセスにメモリが食い潰されていたらしい。

というわけで適度な個数に制限することで、メモリの浪費を防ぎパフォーマンスを保てるわけである。

/etc/php-fpm.d/www.conf にて、下記の通り設定した。

pm = static
pm.max_children = 4

これが一番効いたかな。


他にもこういうものはある。ApacheもDovecotもそうである。

Apacheだとこんな感じで

StartServers 2
MaxClients 2
MaxRequestsPerChild 128

プロセス数2は少なすぎるかなぁ。

Dovecotについては、imap-loginが標準設定ではログイン要求毎に作られるのが問題で、

これは多くのログイン要求(総当たり攻撃も含む)でプロセス数が際限なく増えてしまうということである。

ただし、imap-loginをログイン用要求毎にプロセスを作るのはセキュリティ強化のための方法らしく、

下記の設定はパフォーマンス重視の設定であることに注意が必要である。

/etc/dovecot/conf.d/10-master.confにて、

service imap-login {
  (略)
  service_count = 0

これでもimapプロセスは接続毎にできるけど、これは実際使われている分なので仕方ないということで。


こんな対策でとりあえずメモリの空きは確保できるようになった。

ただ、やっぱりきついですね。RAM 1GBのVPSは無謀だったかなぁ。

いろいろあるかもしれないけど、パフォーマンスは犠牲にしても、

なにかあっても身動きが取れなくなるほど悪化することは避けられるようにカスタマイズしていきたい。


あとSSHのログインが遅い件については、こういうカスタマイズもした。

ログイン時の処理で使っていないもの、あまり意味のないものを切ったという話。

UseDNS no
GSSAPIAuthentication no

もちろんGSSAPIを使っている人は有効にしないといけませんが。