php-fpmあれこれ
ドキュメント
参考になりそうなもの
------------------
pm
プロセスマネージャー
dynamic
最低プロセスと最大プロセスを決めておき、リクエストに応じてプロセスが決まる。
メモリの節約をしつつ決定できる
static
プロセス数を常に一定に固定する方法。
CPUに優しいが、アクセスが少ない時もプロセスが貯まるのでメモリを占有する
ondemand
最大プロセス数を決めて、dynamicと同じようにリクエストに応じてプロセスが増える。
CPUに負荷がかかるが、プロセスがキルされるのでメモリの占有率はdynamicより低い。
pm.max_children
子プロセスの最大プール数
基本的にCPUのコア数に合わせるのが良いとのことだが。
=同時に処理できる子プロセスの最大数。大きすぎるとOOM Killerでkillされる。
この値を超えると待ち or 502になる
基準となる値の考え方
サーバの空きメモリから常駐しているアプリのマージン(キャッシュ膨張や将来の伸び、予備分)を差し引く
そのメモリをFPMの子プロセスとして使うようにする
1プロセスが平均でどのくらいの量を使うのか、調べる
code:例.sh
total used free shared buff/cache available
Mem: 15588 4373 7443 880 3771 10001
Swap: 0 0 0
deployer@ip-192-168-0-96 ~$ ps --no-headers -o rss,cmd -C php-fpm | grep 'pool www' | awk '{ sum+=$1; n++ } END { printf "平均RSS: %.1f MB\n", sum/n/1024 }' 平均RSS: 83.3 MB
コマンド説明
code:sh
# php-fpmのコマンドのプロセスを出力
# 出力するのはrss(Resident Set Size:常駐メモリ量), コマンド
19080 php-fpm: master process (/etc/php-fpm.conf)
38348 php-fpm: pool www
37476 php-fpm: pool www
36212 php-fpm: pool www
36436 php-fpm: pool www
36112 php-fpm: pool www
36512 php-fpm: pool www
wwwでgrepする(子プロセスだけとる)
awkでRSS合計 / 子プロセス / 1024で1つ当たりのRSSをとる
この場合、10001MB余裕があり、子プロセス1つ当たり83MB程度使う
10001MBから、常駐アプリケーション分のメモリを差し引く
code:例.sh
# 常駐マージンの計算
awk '/MemAvailable/ {printf "MemAvailable: %d MB\n", $2/1024}' /proc/meminfo
MemAvailable: 10047 MB (使えるメモリは10001MB)
# 詳細な常駐の計算...
for SVC in nginx mysqld mariadbd redis-server node; do total_kb=$(ps --no-headers -C $SVC -o rss 2>/dev/null | awk '{s+=$1} END{print s+0}'); if "$total_kb" -gt 0 ; then printf "%-12s %6.1f MB\n" "$SVC:" "$(echo "$total_kb/1024" | bc -l)"; fi; done nginx: 24.8 MB
redis-server: 5.7 MB
とかあれこれやると日が暮れてしまうので、今回は多少ざっくり計算してしまおう。
合計2GBとしてみる
nginx 25MB
その他あれこれ 925MB
バッファ 1GB
10001 - 2000 = 8001MB使える。8001 / 83.3 = 96.05...
なので、この値には96付近の値を入れると吉
pm.start_servers
プロセス開始時に生成される子プロセス
php-fpmをrestartしたときでもリクエストが絶えず飛んで来る環境なら、少し多めにしておこう
min < start < max くらいの値が妥当。
pm.min_spare_servers
アイドル状態で残しておく子プロセスの数。急な増加に強い。
大きい値にしすぎると駐在しすぎてメモリを食う。
cpuコア数分が基本だが、プロセスを食いやすい設計の場合は注意。
pm.max_spare_servers
アイドル状態で残しておく子プロセスの数。
小さくしすぎると、すぐ生成されることになりCPU負荷が増える。
大きい値にしすぎるとスパイク耐性が上がるが駐在しすぎてメモリを食う。
cpuコア数 * 2-4くらいがよい。
pm.max.requests
この数のリクエストをこなしたらプロセスを終了し、再生成する
定期的に生成するようにすることでメモリリーク対策になり、長時間稼働でも安定化するようになる。
ある程度この値は静的な値で良い。ベースの1000から様子を見てあげていこう。
request_terminate_timeout
リクエストの最大処理時間。
無限ループや重い処理をkillして負荷が貯まるのを防ぐ。