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

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

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

この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など使うにも、週に数件、出るか出ないかわからないもののためにELB配下のサーバ全てでtcpdump使うのは厳しいです。

なかなか調査が進みません。

原因

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

ELBのノードを交換してもらったり、EC2側も色々チューニングしたり、Apacheバージョン換えたり設定変えたり、Nginxにしてみたり、カーネルチューニングしてみたり、かなり頑張ったのですが何も効果無かったです。

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

対策

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

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

参考URL

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

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