メモリ枯渇の背景
仕事で、PHPのPhalcon FWで作ったAPIアプリケーションが乗ったphp-fpmサーバを運用しているのですが、 こやつで大量のリクエストをさばけるよう、負荷試験を行ってチューニングした結果、 現在php-fpmプロセスは、staticでリクエストを待つようになっています。
そのせいなのか、リクエストが少ないとプロセスのリフレッシュまで時間がかかり、 結果、APIサーバのメモリを食い潰すという事態にちょいちょいなります。
これは負荷試験で大量リクエストを投げているときは出てこない事象なので、完全に盲点でした。
問題発覚後は、設定値チューニングしたり、php-fpmをreloadしたりして適時対応してきたのですが、 本日ふと、サーバ上のメモリのほとんどが、reloadでも開放されていないことに気付きました。
・解放前 $ free -m total used free shared buffers cached Mem: 7871 7592 279 1 167 308 -/+ buffers/cache: 7116 755 Swap: 1023 0 1023 ・reloadで解放 $ sudo service php-fpm reload Reload service php-fpm done ・解放後 $ free -m total used free shared buffers cached Mem: 7871 5080 2791 1 167 308 -/+ buffers/cache: 4603 3267 Swap: 1023 0 1023
そういえば、php-fpmのrestart/reloadは公式ドキュメントにGracefull restartと書かれていますが、 実際には期待する動作をしませんでした。この件の対応法についてはまた別途記事にしようと思います。
メモリ使用の詳細を確認する
以下のコマンドでメモリ情報を確認したところ、Slabという領域が4Gほど確保していることに気付きました。
$ view /proc/meminfo
Slabとは?
わからなかったので調べました。
以下のサイトにお世話になった結果、どうもKernelキャッシュの一種のようですね。
詳細はリンク先で☆
Slabキャッシュをクリアした話 – CLARA ONLINE techblog
Slabキャッシュの確認
slabtop
コマンドで上位2つの消費が多いものを見たところ、
参考サイトと同様にdentryのキャッシュが肥大化しているようでしたので、
このキャッシュをクリアすることにしました。
Slabキャッシュのクリア
以下が各フェーズの実行結果です。
・slabtopの結果(reload後) OBJS ACTIVE USE OBJ SIZE SLABS OBJ/SLAB CACHE SIZE NAME 20941060 20940019 99% 0.19K 1047053 20 4188212K dentry 302198 301745 99% 0.06K 5122 59 20488K size-64 ・Slabキャッシュクリアとその後のfree # sync # echo 2 > /proc/sys/vm/drop_caches # free -m total used free shared buffers cached Mem: 7871 791 7080 1 167 56 -/+ buffers/cache: 567 7304 Swap: 1023 0 1023 ・slabtopの結果(Slabキャッシュクリア後) OBJS ACTIVE USE OBJ SIZE SLABS OBJ/SLAB CACHE SIZE NAME 110580 110572 99% 0.19K 5529 20 22116K dentry 83068 82608 99% 0.20K 4372 19 17488K vm_area_struct
drop_cachesを変更するにはrootになって実行する必要がありました。
Slabキャッシュクリアの結果
freeコマンドの結果だけからもわかるように、3Gなかったメモリの空き量が、 一気に7Gまで上昇しました。これはすごい!
そしてその後の経過を1日Zabbixで見守っていたのですが、 クリアしたSlabキャッシュをすぐに同じレベルまで確保することはなさそうでしたし、 アプリケーションにも不具合が出てなかったので、この対応で一旦メモリ枯渇の心配は(しばらく)なくなりました。
結論
アクセスが少ないうちは、php-fpmのプロセス管理をdynamicにしましょう。