AWS ELBの504ステータスのGateway Timeoutと格闘した話(最終的にALBで直った)

ELBのメトリクスのステータスにはバックエンドEC2が返したステータス(HTTPCode_Backend_XXX)と、ELB自身のステータス(HTTPCode_ELB_5XX)があります。

ELB自身のステータスコードの中には504というエラーコードがあります。このエラーと格闘した話を書きます。

このELBのステータスコード504ですが、CloudWatchのメトリクスで言うとHTTPCode_ELB_5XXに上がってきます。

このメトリクスは5XXという名前の通り、504以外のコードも含んでいます。

  • HTTP 502: Bad Gateway (バックエンドサーバからのレスポンスがHTTPレスポンスとして解釈不能)や、
  • HTTP 503: Service Unavailable (突発的なアクセス増によりスケールが間に合わない時など)

などがあります。

実際に504かどうかはS3に保存されたアクセスログを見ると確認することができます。

docs.aws.amazon.com

他のエラーも発生してトラブルシュートしたことはあるのですが、どれも上記のリンクの説明読んだり、調査したり、AWSサポートと連携したりで問題無く原因特定できました。しかし、 HTTP 504: Gateway Timeout は全く原因がわからない。

HTTP 504: Gateway Timeoutとは

では HTTP 504: Gateway Timeout とはどんなステータスなのでしょう。

Timeoutという名前の通り何かがタイムアウトした際に出るエラーです。具体的には、ELBからEC2にリクエストを投げて返ってくるまでの時間(Backend Processing Time)が、ELBのアイドルタイムアウトに設定した値を超えると発生します。

f:id:yomon8:20161231124726p:plain

実際に、ELBのアイドルタイムアウトをデフォルトの60秒だとして、60秒以上Sleepする処理をELB経由でEC2側で動かせばエラーを再現できます。

504が散発した

当時、ELBで運用していたら504が散発しました。

時々日に100件などの単位で大量に発生する場合もありますが、それはELB自体がおかしい可能性が高いのでAWSサポートに頼めば、ELBノードを交換してもらえる時があります。

問題なのは、低頻度(週に2〜3件とか)の単位で発生する504エラーで以下のような何も問題無く見える場合です。

  • バックエンド処理が重いということは無く、小さな静的ファイルを返すだけでも発生する場合がある
  • アクセス数と発生数は比例しない(アクセス数が高くても低くても発生する)
  • EC2側のApacheやNginxは正常に応答しているように見える

tcpdumpなどで調査するにも発生頻度の低さで調査が進みません。

原因

AWSの方々とも何度も何度もやりとりしたのですが、結局原因わからずです。

EC2側も色々チューニングしたり、Apacheのバージョン換えたり設定変えたり、Nginxにしてみたり、カーネルチューニングしてみたり、全部この件には効果無かったです。

AWS ELB配下のApache Http Server推奨設定のAWS公式情報 - YOMON8.NET

対策

対策は題名の通りです。ALBにしたら全く発生しなくなりました。

気持ちとしては釈然としないのですが、ブラックボックスのELB側を見れない以上調査も難しく時間かかるので、同じ事象に遭遇している人がいれば、まずはALBにしてみるのも手かと思います。運用整備する工数の方が恐らく小さくなるのではと思います。

参考URL

ELBの挙動とCloudWatchメトリクスの読み方を徹底的に理解する | Developers.IO

Elastic Load Balancing でのレイテンシーのトラブルシューティング