aws の ec2 にて、 nginx + php-fpm(7.1) の環境を構築したらメモリ使用率が徐々に上昇していく現象に出くわした。
で、対応したので、そのメモ。
生じた環境
- Amazon Linux AMI 2017.09.1 (HVM), SSD Volume Type - ami-2803ac4e
- nginx
- php-fpm(7.1)
調べたら https://qiita.com/bezeklik/items/7e1ac9e5da39261be7bd や http://s-tajima.hateblo.jp/entry/2015/02/20/233615 などにある、 slab_cache の問題だった。
原因は http://s-tajima.hateblo.jp/entry/2015/02/20/233615 にとても詳しく書いてあるので、そちらを参照して下さい。(参考になりました!ありがとうざいます!)
要は、 https へのリクエストを curl で行っている時に slab_cache(dentry cache) が溜まっていき、結果メモリが圧迫されるらしい。
上記環境にて稼働しているアプリケーションは Guzzle を用いて定期的に https へリクエストを出していた。
つまり、これが原因。
起きている状況の確認
dentry cache の使用状態を以下のコマンドで調べる。
$ sudo slabtop -o | grep dentry
おそらく、それなりに使用されてしまっているので、次に、以下のコマンドで dentry cache を開放する。
$ sudo sh -c "echo 2 > /proc/sys/vm/drop_caches"
再度、前述の $ sudo sh -c "echo 2 > /proc/sys/vm/drop_caches"
で使用状況を確認し、 dentry cache が減っていることを確認する。
次に、 curl を用いて https へリクエストを出してみる。
今回は、 php スクリプトを呼び出すことで実現されるので、対象のスクリプトを呼び出した。
改めて、 $ sudo slabtop -o | grep dentry
で確認すると、1回スクリプトを呼び出すたびに増えていくことが確認できる。
対策(Ansible 使いたかったのでその前提で。)
まず、上記の通り、以下のコマンドで dentry cache を削除しておく。(これは手動でやった。)
$ sudo sh -c "sync; echo 2 > /proc/sys/vm/drop_caches"
※ sync もしておく。
次に、 php-fpm に環境変数として NSS_SDB_USE_CACHE: yes
を渡す。
具体的には /etc/php-fpm.d/env.conf
を追加して、以下の設定を適用する。
[www]
env[NSS_SDB_USE_CACHE] = "YES"
/etc/php-fpm.conf
に追記するなどの方法もあるが、 Ansible で行いたかったので、
/etc/php-fpm.d/env.conf
を templates から配置するようにした。
具体的には、 ./roles/php/templates/env.conf.j2
というファイルを用意して、上記と同じ内容を記載。
[www]
env[NSS_SDB_USE_CACHE] = "YES"
タスクファイルで以下を実行するように設定する。
- name: publish /etc/php-fpm.d/env.conf
template: src="env.conf.j2" dest="/etc/php-fpm.d/env.conf"
なお、この方法は /etc/php-fpm.d/*.conf
が自動的に読み込まれるように /etc/php-fpm.conf
に書いてある前提です。
その他
そもそもの原因は curl で https へのリクエストを出すことで生じるので、 php スクリプトしか動作しない前提などであれば、上記で問題は無いはず。
もし、他のスクリプトなどで実行する場合は、それらに適した方法があると思われます。
あまり望ましい方法ではないかもしれませんが、 cron で sudo sh -c "sync; echo 2 > /proc/sys/vm/drop_caches"
を設定しておく、という方法もありかもしれません。
というメモ。