PHP-FPM ワーカー不足で高負荷時に応答が遅延する『Web/DBの話⑤』
普段は問題ない。
でもアクセスが増えた瞬間、急にレスポンスが遅くなる。
Apache も Nginx も生きている。DB も落ちていない。
原因は PHP-FPM のワーカー(プロセス)不足。
Web運用でかなり多い、しかも「分かりにくい」詰まり方だ。
冒頭の一言要約
PHP-FPM は“窓口制限”。
ワーカー数が足りないと、リクエストは中で待たされる。
症状(あるある)
高負荷時だけページ表示が遅い
タイムアウトが断続的に発生
Webサーバは軽いのに応答が返らない
PHP 処理が終わるまで待たされる
再起動すると一時的に直る
夜間バッチや管理画面操作で急に遅くなる
原因と仕組み(なぜ起きるか)
PHP-FPM の max_children が小さい
pm=dynamic / ondemand の挙動を理解していない
同時実行数が想定より多い
PHP処理が重く、ワーカーが長時間占有される
Webサーバの同時接続数と整合が取れていない
ワーカー不足を CPU や DB の問題と誤診する
PHP-FPM は
「同時に処理できる PHP の数」が上限で決まる。
超えた分はエラーではなく 待ち行列 になる。
図:ワーカー不足で待ちが発生する
[リクエスト]
│
▼
[PHP-FPM]
[Worker][Worker][Worker] ← max_children
│
▼
待ち行列 → 応答遅延
切り分け(最短コース)
PHP-FPM のステータス確認
pm.status_path = /status
max_children に到達していないか
max active processes
listen queue が増えていないか
現在の設定確認
pm pm.max_children pm.start_servers pm.max_spare_servers
PHP処理時間の確認
スロークエリ
外部API呼び出し有無
再現条件の確認
アクセス集中時のみか
バッチ同時実行時か
今すぐ効く対処(テンプレ)
◆ PHP-FPM 設定例(dynamic)
pm = dynamic
pm.max_children = 20
pm.start_servers = 5
pm.min_spare_servers = 5
pm.max_spare_servers = 10
◆ ワーカー数の考え方(目安)
メモリ / 1プロセス使用量 = max_children
例:
メモリ 8GB
PHP-FPM 1プロセス 200MB
→ max_children ≒ 30〜35
◆ 設定反映
systemctl reload php-fpm
恒久対策/再発防止チェックリスト
max_children を実測メモリで設計
pm モード(dynamic / ondemand)を理解
PHP-FPM ステータスを監視
高負荷処理(バッチ)を時間帯分離
重い PHP 処理を非同期化
Web同時接続数と整合を取る
再起動で直る運用をやめる
負荷テスト時に listen queue を確認
落とし穴(やりがちミス)
max_children を闇雲に増やす(OOM発生)
CPU問題だと誤診する
Apache/Nginx だけチューニング
ondemand の挙動を誤解
ステータスを有効化していない
まとめ(行動指針)
PHP-FPM は
「同時実行数の上限」を意識しないと必ず詰まる。
処理時間を把握 → ワーカー数を設計 → 待ち行列を監視。
この3点を守るだけで、
高負荷時の謎の応答遅延はほぼ消える。
