Classic Load Balancer の使用中に返された 504 エラーをトラブルシューティングするにはどうすればよいですか?

最終更新日: 2018 年 3 月 21 日

問題

Classic Load Balancer のアクセスログ、Amazon CloudWatch メトリクス、または Classic Load Balancer 経由でサービスに接続したときに HTTP 504 エラーが表示されます。この問題を解決する方法を教えてください。

解決方法

HTTP 504 エラーは、ゲートウェイまたはプロキシがタイムアウトしたことを示す HTTP ステータスコードです。トラブルシューティングを行う際には、次の点について調査してください。

ロードバランサーのアイドルタイムアウトを確認し、必要に応じて変更します。

ロードバランサーが HTTP 504 エラーを返す最も一般的な理由は、対応するバックエンドインスタンスが、現在設定されているアイドルタイムアウト内に、リクエストに応答しなかったことです。デフォルトでは、Classic Load Balancer のアイドルタイムアウトは 60 秒です。

CloudWatch メトリクスが有効になっている場合は、ロードバランサーの CloudWatch メトリクスを確認します。ロードバランサーで設定されているタイムアウト時間と、レイテンシーのデータポイントの値が等しく、HTTPCode_ELB_5XX メトリクスにデータポイントが存在する場合には、少なくとも 1 つのリクエストでタイムアウトが発生しています。

これを解決するには、ロードバランサーのアイドルタイムアウトを変更して、HTTP リクエストがアイドルタイムアウト期間内に完了するようにするか、アプリケーションを調整してより迅速に応答するようにします。

バックエンドインスタンスで接続が開いたままになっていることを確認する

ロードバランサーがアイドル状態のタイムアウトに達する以前に、バックエンドインスタンスによりロードバランサーへの TCP 接続が終了された場合、ロードバランサーはリクエストに対応できず、HTTP 504 エラーが発生します。

これを解決するには、バックエンドのインスタンスで、keep-alive 設定を有効化します。さらに、keep-alive タイムアウト値を、ロードバランサーのアイドル状態アイムアウトより大きな値に設定します。

(Apache のみ) TCP_DEFER_ACCEPT を無効にする

Apache バックエンドインスタンスに対して TCP_DEFER_ACCEPT が有効になっている場合、ロードバランサーは SYN をバックエンドインスタンスに送信して接続を開始します。バックエンドインスタンスは SYN-ACK で応答し、ロードバランサーは空の ACK をバックエンドインスタンスに送信します。

最後の ACK は空であるため、バックエンドは ACK を受け入れず、代わりに SYN-ACK をロードバランサーに再送信します。この結果、その後 SYN 再試行タイムアウトが発生することがあります。FIN または RST をロードバランサーに送信せずにバックエンドインスタンスが接続を閉じると、ロードバランサーは接続が確立されていない場合でも接続が確立されていると見なします。その後、ロードバランサーがこの TCP 接続を介してリクエストを送信すると、バックエンドは RST で応答し、504 エラーを生成します。

これを解決するには、AcceptFilter http AcceptFilter https の両方を none に設定します。

(Apache のみ) イベント MPM を無効にし、プリフォーク MPM とワーカー MPM を最適に構成する

ロードバランサーに登録されたバックエンドインスタンスではイベント MPM を使用しないでください。Apache バックエンドが動的に接続を閉じると、HTTP 504 エラーがクライアントに送信されるためです。

プリフォーク MPM と ワーカー MPM を使用し、ロードバランサーが 60 秒のアイドルタイムアウトに設定されていることを前提として、最適なパフォーマンスを得るには、次の値を使用します。

  mod_prefork MPM mod_worker MPM
タイムアウト 65 65
キープアライブタイムアウト 65 65
キープアライブ オン オン
MaxKeepAliveRequests 10,000 0
AcceptFilter http なし なし
AcceptFilter https なし なし