🪼

ALB・Nginx・PHP のタイムアウト管理

に公開

🐱 はじめに

Webアプリケーションの運用では、ロードバランサーやWebサーバー、アプリケーションの各レイヤーで適切な接続管理が重要です。本記事では、AWS ALB、Nginx、PHP-FPMの各レイヤーにおけるタイムアウト設定のチューニングポイントを解説します。

⛓️ システム全体の接続フロー

ALB + Nginx + PHP-FPM構成では、クライアントからアプリケーションまで、以下のような複数の接続を経由します。

[クライアント] ←→ [ALB] ←→ [Nginx] ←→ [PHP-FPM]
      ①             ②           ③
  1. 接続①: クライアント ↔ ALB
  2. 接続②: ALB ↔ Nginx
  3. 接続③: Nginx ↔ PHP-FPM

タイムアウトは、これら個々の接続に対して設定する必要があり、それぞれが連携して正しく動作することが重要です。

🎯 タイムアウト設定の考え方と全体設計

タイムアウト設定の基準となるのは PHP実行時間 です。この値をもとに、接続の種類に応じて適切な設定を行います。

⏰ タイムアウト設定の優先順位と連鎖関係

※()内は定義場所を表します

                        設定値決定の優先順位
                              ┌─────────────────┐
                              │ 1️⃣ PHP実行時間    │
                              │   (php.ini)     │ 
                              └─────┬───────────┘
                                    │ 基準として
                                    ▼
                        ┌─────────────────┐
                        │ 2️⃣ ALB設定       │
                        └─────┬───────────┘
                              │ 
                    ┌─────────┴─────────┐
                    ▼                   ▼
          ┌─────────────────┐   ┌─────────────────┐
          │ 3️⃣ Nginx処理関連  │   │ 4️⃣ Nginx接続関連 │
          │  (nginx.conf)   │   │  (nginx.conf)   │
          └─────┬───────────┘   └─────────────────┘
                │
                ▼
          ┌─────────────────┐
          │ 5️⃣ PHP-FPM設定   │
          │   (www.conf)    │
          └─────────────────┘

設定値の決め方

1. PHP実行時間を決める

基準: 実際のアプリケーションで最も時間がかかる処理を測定し、余裕を持った値を設定

測定方法

  • ログで処理時間を確認
  • 重い処理(レポート生成、画像処理など)を実際に実行

設定例

  • 通常の処理:5〜10秒
  • 重い処理:80秒
  • 設定値:120秒(余裕を持たせた値)

2. 他の設定値を連動させる

基本的な考え方

  • ALB idle_timeout: PHP実行時間以上に設定
  • Nginx fastcgi_read_timeout: PHP実行時間より長く設定(処理完了を待てるよう余裕を持たせる)
  • Nginx keepalive_timeout: ALB idle_timeoutより長く設定

🌐 タイムアウトの土台:TCPとKeep-Alive

Nginxのkeepalive_timeoutなどの設定を深く理解するために、その背景にあるTCP接続とKeep-Aliveの仕組みを簡単に解説します。これらの知識は、なぜタイムアウト設定が重要なのかを理解する助けになります。

TCP接続とは何か? 🤔

TCP(Transmission Control Protocol)は、インターネット上でデータを確実に送受信するための仕組みです。WebブラウザがWebサーバーと通信する際も、この TCP 接続が使われています。

クライアント(ブラウザ)    サーバー(Webサーバー)
        |                        |
        |<------- TCP接続 ------->|
        |                        |
   HTTPリクエスト送信        HTTPレスポンス送信

TCP接続の確立(3-Way Handshake)🤝

TCP接続は「3-Way Handshake」という手順で確立されます。

クライアント                    サーバー
    |                            |
    |----------SYN-------------->|  1. 接続要求
    |                            |
    |<-------SYN-ACK-------------|  2. 接続許可
    |                            |
    |----------ACK-------------->|  3. 接続確認
    |                            |
    |<==== 接続確立完了 ====>|
  1. SYN(同期): クライアントが「接続したい」とサーバーに要求
  2. SYN-ACK(同期-確認): サーバーが「接続OK」と応答
  3. ACK(確認): クライアントが「了解」と確認

この手順により、信頼性の高い通信路が確立されます。

Keep-Alive接続の仕組み 🔄

Keep-Aliveは、一度確立したTCP接続を再利用する仕組みです。

Keep-Alive無し

リクエスト1: 接続確立 → データ送信 → 接続切断
リクエスト2: 接続確立 → データ送信 → 接続切断  ← 毎回接続確立が必要
リクエスト3: 接続確立 → データ送信 → 接続切断

Keep-Alive有り

接続確立 → リクエスト1 → リクエスト2 → リクエスト3 → 接続切断
           ↑                                    ↑
      同じTCP接続を再利用                 まとめて切断

🔧 具体的な設定項目

この基本方針に基づき、各レイヤーで重要となる具体的な設定項目を紹介します。
これらの値を適切に設定することが、予期せぬエラーを防ぎ、システムを安定稼働させる鍵となります。

📊 設定項目一覧表

設定項目 場所 何をするもの? デフォルト値 設定考慮点 関連問題
idle_timeout ALB クライアント接続維持時間 60秒 PHP実行時間以上に調整 504エラー
keepalive_timeout Nginx Keep-Alive接続維持時間 75秒 ALB idle_timeoutより長く リソース浪費
client_header_timeout Nginx リクエストヘッダー受信待機 60秒 モバイル環境を考慮 408エラー
client_body_timeout Nginx リクエストボディ受信待機 60秒 ファイルアップロード考慮 408エラー
send_timeout Nginx 応答送信待機時間 60秒 アプリ要件に基づき設定 -
fastcgi_connect_timeout Nginx PHP-FPM接続待機時間 60秒 アプリ要件に基づき設定 -
fastcgi_send_timeout Nginx PHP-FPMリクエスト送信待機時間 60秒 ファイルアップロード考慮 502エラー
fastcgi_read_timeout Nginx PHP-FPM応答待機時間 60秒 PHP実行時間より長く設定 502エラー
max_execution_time PHP PHPスクリプト最大実行時間 30秒 アプリ要件に基づき設定 504/502エラー
request_terminate_timeout PHP-FPM プロセス強制終了時間 0 (無効) PHP実行時間より長く 502エラー
pm.process_idle_timeout PHP-FPM アイドルプロセス終了時間 10秒 リソース効率を考慮 リソース浪費

⚠️ 注意: 具体的な数値は環境やアプリケーション要件によって異なるため、実際の処理時間を測定して決定することが重要です。

⚠️ よくあるエラーと解決方法

❌ 504 Gateway Timeout

「長時間の処理でタイムアウトする」

  • 原因: PHPの処理時間がALBの制限時間を超過
  • 症状: ユーザーのブラウザにタイムアウトエラーが表示
  • 解決方法: ALBのidle_timeoutをPHP実行時間以上に設定

❌ 502 Bad Gateway

「処理中に突然エラーになる」

  • 原因: PHPの処理中にNginxがタイムアウト
  • 症状: NginxとPHP-FPM間の通信が切断
  • 解決方法: Nginxのfastcgi_read_timeoutをPHP実行時間より長く設定

❌ 408 Request Timeout

「ファイルアップロード時にエラーになる」

  • 原因: 遅いネットワーク(モバイル回線など)でのリクエスト送信
  • 症状: Nginxがリクエスト受信中にタイムアウト
  • 解決方法: client_body_timeoutclient_header_timeoutを調整

⚠️ リソース浪費

「サーバーのメモリ使用量が増え続ける」

  • 原因: 接続やPHPプロセスが長時間残存
  • 症状: メモリ不足やパフォーマンス低下
  • 解決方法: 適切なタイムアウト値とプロセス管理設定

📊 設定後の確認ポイント

  • 5XXエラーの状況: CloudWatch ALB メトリクスでHTTP 5XXエラー数を確認
  • 接続の安定性: ALB Target Connectionsの変化を確認
  • レスポンス時間: ALB Target Response Timeの変化を確認

🩵 おわりに

タイムアウト設定は「一度設定すれば終わり」ではありません。アプリケーションの成長に合わせて継続的に見直しを行いましょう。

もしご指摘やアドバイスがありましたら、コメントいただけますと幸いです📝
えみり〜でした|ωΦ)ฅ

🔗 参考資料

Discussion