事象
現在稼働中の社内システムをSSL化した際にメモリの消費量が不安定になり、16GBあるメモリが時折200MB以下まで低下し、 Out of memory: Kill process
が発生していた。
当初はこの原因について、サーバの容量が足りないことや、PHPのスケジュールされているタスクが原因ではないかと予想し、httpdプロセスの定期killやスケジュールされたスクリプトの見直し、サーバの増強やそれに伴う移行を行ったが改善されず。
特にOOM Killerが発動した際にサーバが数秒程度レスポンスエラーとなり、502などを返す事象が発生していたため、重要度の高いものだった。
環境
- Conoha VPS 4core 16GB
→ AWS 1core 4GB x4 (Auto Scaling)でも発生 - PHP 5.6.40
- Apache 2.4.x
- CakePHP 2.10
原因(推定)
ApacheとPHP ZTSモードの組み合わせが原因。
ApacheのMPMはevent駆動型で動作しており、PHPはZTS(Zend Thread Safe)モードで動作していた。event駆動型は本来複数の子プロセスで動作する効率的な駆動方式だが、PHPで本番運用が推奨されていないZTSモードが使用されていたことにより、うまくプロセス管理が出来ずにメモリリークが発生していたものと思える。
対処(暫定)
ApacheのMaxRequestsPerChild
を30と極端に低く設定して対処。これにより暫定的だが定期的にプロセスの再起動が行われ、ついでにメモリが開放される仕組み。
原因を根本的に解決するにはApacheかPHPの動作モードを変更する必要があるが、これは大きな変更となるため、サーバの停止時間や副次的な不具合等を考慮してこの方法は取らなかった。
この対応により、今のところ定期的にプロセスがkillされてメモリが開放され安定して動作するようになった。プロセス再起動頻度が上がることによってCPU使用率が高くなるということもなかった。
現在は、そもそもApacheのスペック的に考えてコスト面などの観点から、Nginxに差し替えることを検討中。苦労してAWSに移行してリソース分散させた甲斐があった。