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 エラーを生成します。
これを有効にするには、バックエンドインスタンスでキープアライブ設定を有効にして、キープアライブのタイムアウトに、ロードバランサーのアイドルタイムアウトよりも大きな値を設定します。
(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 のみ) event MPM を無効にして、prefork MPM および worker MPM に最適設定を構成する
event MPM はロードバランサーに登録されるバックエンドインスタンスでは使用すべきではありません。理由は、Apache バックエンドインスタンスで接続が動的に閉じられるため、クライアントに HTTP 504 エラーが送信されることになるためです。
ロードバランサーに 60 秒のアイドルタイムアウトが設定されていると仮定した場合、prefork MPM と worker MPM を使用する際に最適性能を達成するには、以下の値を使用してください。
|
mod_prefork MPM |
mod_worker MPM |
|
タイムアウト |
65 |
65 |
|
KeepAliveTimeout |
65 |
65 |
|
KeepAlive |
オン |
オン |
|
MaxKeepAliveRequests |
10000 |
0 |
|
AcceptFilter http |
none |
none |
|
AcceptFilter https |
none |
none |