見出し画像

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
        │
        ▼
      待ち行列 → 応答遅延

切り分け(最短コース)

  1. PHP-FPM のステータス確認

    1. pm.status_path = /status

  2. max_children に到達していないか

    • max active processes

    • listen queue が増えていないか

  3. 現在の設定確認

    1. pm pm.max_children pm.start_servers pm.max_spare_servers

  4. PHP処理時間の確認

    • スロークエリ

    • 外部API呼び出し有無

  5. 再現条件の確認

    • アクセス集中時のみか

    • バッチ同時実行時か


今すぐ効く対処(テンプレ)

◆ 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点を守るだけで、
高負荷時の謎の応答遅延はほぼ消える。

いいなと思ったら応援しよう!