事象
PHPをECS(Fargate)上で動かすシステムを構築しましたが、メモリリークが発生していました。
そこで、よくある手法である pm.max_requests をセットしてphpのプロセスを再起動させました。
ところが、プロセス再起動して一時的にメモリは解放されますが、下図のようにすぐにまたメモリリークの水準ラインにもどってしまいました。
これは、php側が原因ではないと推測。
いろいろググったところ、HTTPS通信を行う際にはNSSライブラリを参照しており、このNSSにバグがあって、dentryキャッシュ が肥大化するらしいことを発見
↓参考
https://qiita.com/ldr/items/4b39fdcb8fae7d09f406
<NSSとは>
Network Security Services (NSS) は、SSLをサポートするオープンソース暗号化ライブラリのセットです。
cURLなどの複数のLinuxツールはNSSを使用して、信頼されるSSL通信を確認します。
<dentryキャッシュとは>
dentry キャッシュは、 RAMより低速なHDDやSSDなどの、二次記憶装置からのディレクトリエントリの読み取りをキャッシュしておき、高速化するものです。
ファイル名やディレクトリの階層構造、またディレクトリ名とinode情報を関連付けるもの(構造体)。
対策
以下の記事を参考にしました。
https://blog.nomadscafe.jp/2014/01/tmpfile-and-dentry-cache.html
対策として、以下の vm.drop_caches を使う方法があるそうなのでやってみたところ
echo 2 > /proc/sys/vm/drop_caches
以下エラーで怒られました。
bash: /proc/sys/vm/drop_caches: Read-only file system
どうやらホスト上でルートとして実行する必要があるらしく、Fargate(Docker:ゲスト)なので、ダメっぽいです。
https://discuss.linuxcontainers.org/t/how-to-drop-caches-inside-a-container/3200
次に試したのが tmpfs を使う方法で、tmpfsだと、dentry cacheは溜まらないそうです。
以下のコマンドを試しました
export TMPDIR=/dev/shm
すると、dentryキャッシュが99%のところで増加がとまりました。
なので、この方法を採用しようと思いました。
具体的には、phpの設定ファイル www.conf の最後に以下コードを追記して、再デプロイしました。
env[TMPDIR] = "/dev/shm"
やっとメモリリークが止まりました。
以上
参考サイト
https://blog.nomadscafe.jp/2014/01/tmpfile-and-dentry-cache.html
https://discuss.linuxcontainers.org/t/how-to-drop-caches-inside-a-container/3200
https://hiboma.hatenadiary.jp/entry/20140212/1392131530