ALB・Nginx・PHP のタイムアウト管理
🐱 はじめに
Webアプリケーションの運用では、ロードバランサーやWebサーバー、アプリケーションの各レイヤーで適切な接続管理が重要です。本記事では、AWS ALB、Nginx、PHP-FPMの各レイヤーにおけるタイムアウト設定のチューニングポイントを解説します。
⛓️ システム全体の接続フロー
ALB + Nginx + PHP-FPM構成では、クライアントからアプリケーションまで、以下のような複数の接続を経由します。
[クライアント] ←→ [ALB] ←→ [Nginx] ←→ [PHP-FPM]
① ② ③
- 接続①: クライアント ↔ ALB
- 接続②: ALB ↔ Nginx
- 接続③: 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
: ALBidle_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. 接続確認
| |
|<==== 接続確立完了 ====>|
- SYN(同期): クライアントが「接続したい」とサーバーに要求
- SYN-ACK(同期-確認): サーバーが「接続OK」と応答
- 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_timeout
やclient_header_timeout
を調整
⚠️ リソース浪費
「サーバーのメモリ使用量が増え続ける」
- 原因: 接続やPHPプロセスが長時間残存
- 症状: メモリ不足やパフォーマンス低下
- 解決方法: 適切なタイムアウト値とプロセス管理設定
📊 設定後の確認ポイント
- 5XXエラーの状況: CloudWatch ALB メトリクスでHTTP 5XXエラー数を確認
- 接続の安定性: ALB Target Connectionsの変化を確認
- レスポンス時間: ALB Target Response Timeの変化を確認
🩵 おわりに
タイムアウト設定は「一度設定すれば終わり」ではありません。アプリケーションの成長に合わせて継続的に見直しを行いましょう。
もしご指摘やアドバイスがありましたら、コメントいただけますと幸いです📝
えみり〜でした|ωΦ)ฅ
Discussion