# AWS 504 Gateway Timeout エラー完全解決ガイド
AWS Elastic Beanstalk で重たい処理を実行した際に、504 Gateway Timeout エラーが発生しました。CloudWatch のメトリクスではHTTPCode_ELB_5XXに記録されます。
本記事では、504 エラーの原因と解決方法を詳しく解説します。
# HTTP 500 系エラーの種類
HTTP 500 系のエラーには、以下のような種類があります。
| コード | サーバーステータス説明 |
|---|---|
| 500 | Internal Server Error サーバーエラー |
| 501 | Not Implemented リクエスト不能 |
| 502 | Bad Gateway レスポンス不能 |
| 503 | Service Unavailable リクエスト処理できない |
| 504 | Gateway Timeout 時間タイムアウト |
| 505 | HTTP Version Not Supported HTTP バージョンサポートなし |
| 506 | Variant Also Negotiates ネゴシエーションエンドポイントエラー |
| 507 | Insufficient Storage サーバー容量不足 |
| 508 | Loop Detected ループ入ってます |
| 510 | Not Extended 拡張サポートなし |
| 511 | Network Authentication Required 認証エラー |
502-504 エラーが一般的でよく見られます。プログラムスペルミスなどでよく 503 起こります。507 エラーはたまにサーバーの容量不足で起こります。何年かに一回出て、長年会ってない親戚みたいな気持ちになります。
# 504 エラーの原因調査
今回の AWS 504 timeout エラーの原因として、以下の 4 つを調査しました。
| 項目 | 結果 | 備考 |
|---|---|---|
| プログラムソース | 問題なし | 普段は正常に動作し、重たい処理の時だけ発生するため、プログラムの可能性は低い |
| CloudFront | 該当なし | CloudFront は使用していない |
| サーバー設定 | 要確認 | Apache のタイムアウト設定が原因の可能性 |
| ロードバランサー | 要確認 | ELB のアイドルタイムアウト設定が原因の可能性 |
調査のポイント
普段は正常に動作し、重たい処理の時だけエラーが発生する場合は、タイムアウト設定が原因である可能性が高いです。
# 解決方法 1:Apache サーバー設定の変更
Apache のタイムアウト設定を変更することで、504 エラーを解決できる場合があります。
# 推奨設定値
| 設定項目 | 値 | 説明 |
|---|---|---|
| Timeout | 300 | リクエストのタイムアウト時間(秒) |
| KeepAliveTimeout | 300 | KeepAlive 接続のタイムアウト時間(秒) |
| KeepAlive | On | KeepAlive 接続を有効化 |
| MaxKeepAliveRequests | 10000 | 1 つの接続で処理する最大リクエスト数 |
| AcceptFilter http | none | HTTP の AcceptFilter を無効化 |
| AcceptFilter https | none | HTTPS の AcceptFilter を無効化 |
# 設定ファイルの場所
Linux の場合:
/etc/apache2/apache2.conf
Windows XAMPP の場合:
xampp/apache/conf/original/extra/httpd-default.conf
#
# Timeout: The number of seconds before receives and sends time out.
#
Timeout 300
#
# KeepAlive: Whether or not to allow persistent connections (more than
# one request per connection). Set to "Off" to deactivate.
#
KeepAlive On
#
# MaxKeepAliveRequests: The maximum number of requests to allow
# during a persistent connection. Set to 0 to allow an unlimited amount.
# We recommend you leave this number high, for maximum performance.
#
MaxKeepAliveRequests 10000
#
# KeepAliveTimeout: Number of seconds to wait for the next request from the
# same client on the same connection.
#
KeepAliveTimeout 300
# AWS ELB 用 Apache 推奨設定
AWS ELB(Elastic Load Balancer)を使用している場合の推奨設定は以下の通りです。
| 設定項目 | 値 | 説明 |
|---|---|---|
| Timeout | 120 | ELB のアイドルタイムアウト(デフォルト 60 秒)より大きい値に設定 |
| KeepAlive | On | CPU 使用率を削減し、応答時間を改善 |
| KeepAliveTimeout | 120 | Timeout と同じか、それより長い値を設定 |
| MaxKeepAliveRequests | 100 | 単一の TCP 接続で処理するリクエスト数を 100 以上に設定 |
| LogFormat | "%{X-Forwarded-For}i %h %l %u %t \"%r\" %>s %b %D \"%{Referer}i\" \"%{User-Agent}i\"" | X-Forwarded-For ヘッダーを含むログフォーマット |
| AcceptFilter http | none | ロードバランサー使用時は無効化 |
| AcceptFilter https | none | ロードバランサー使用時は無効化 |
設定のポイント
- Timeout: ELB のアイドルタイムアウトよりも大きな値に設定する必要があります
- KeepAlive: CPU 使用率を削減し、応答時間を改善します
- KeepAliveTimeout: Timeout と同じか、それより長い値を選択します
- MaxKeepAliveRequests: 単一の TCP 接続で処理するリクエストの数を 100 以上に設定します
- AcceptFilter: ロードバランサー使用時は、TCP ソケットを「ハーフオープン」状態にするため
noneに設定します
# 解決方法 2:ロードバランサーのアイドルタイムアウト設定変更
# CloudWatch メトリクスで確認
CloudWatch メトリクスを確認し、HTTPCode_ELB_5XXメトリクスにデータポイントが存在する場合、時間内に処理が完了しなかったため、ロードバランサーのアイドルタイムアウトで引っかかった可能性があります。
# 解決方法の選択
以下の 2 つの方法があります。
- アイドルタイムアウト値を変更(コストなし)
- インスタンスの計算能力を上げる(コストあり)
推奨アプローチ
まずはアイドルタイムアウト値を変更してみて、それでも解決しない場合はインスタンスのスケールアップを検討します。
# ロードバランサーのタイムアウト設定変更手順
- Amazon EC2 (opens new window)コンソールを開く
- サイドメニュー[LOAD BALANCING] -> [ロードバランサー]を選択
- 対象のロードバランサーを選択
- [Description]タブ -> [Edit idle timeout]を選択
- [Configure Connection Settings] -> [Idle timeout]の値を1 - 4000 秒に変更
- [Save]を選択
注意
- デフォルトのアイドルタイムアウトは60 秒です
- 最大値は4000 秒(約 66 分)です
- タイムアウト値を長くしすぎると、リソースの無駄遣いになる可能性があります
# 実装時の注意点
AWS 504 Gateway Timeout エラーの解決方法。
Apache サーバー設定の変更
- Timeout、KeepAliveTimeout を適切な値に設定
- ELB 使用時は、アイドルタイムアウトより大きい値に設定
ロードバランサーのアイドルタイムアウト設定変更
- CloudWatch で HTTPCode_ELB_5XX を確認
- 必要に応じてアイドルタイムアウト値を延長(最大 4000 秒)
インスタンスのスケールアップ(最終手段)
- 処理時間を短縮するため、インスタンスタイプを変更
トラブルシューティングの順序
- CloudWatch メトリクスでエラーを確認
- Apache 設定を確認・変更
- ロードバランサーのタイムアウト設定を変更
- それでも解決しない場合は、インスタンスのスケールアップを検討