皆さん、こんにちは!第一線の現場でSRE(サイト信頼性エンジニア)として、日々クラウドのインフラやKubernetesの海を泳いでいるライターの私です。
クラウドの世界へ足を踏み入れたばかりの頃って、次々と現れる謎のエラーコードに頭を抱えちゃいますよね。「サーバーは動いているはずなのに、なんで画面が真っ白に……?」そんな絶望的な瞬間の主犯格としてよく顔を出すのが、今回取り上げる HTTPステータスコード 504 (Gateway Timeout) です。
今回は、AWSの顔とも言えるロードバランサー「ALB(Application Load Balancer)」を舞台に、この 504 エラーがなぜ起きるのか、そしてどうやって解決すればいいのかを、身近な例えを交えながら一歩ずつ優しく紐解いていきましょう!
—
504エラーとは? 郵便配達に例えてイメージしてみよう
まずは、504 Gateway Timeout が世界でどんな風に起きているのか、私たちの身近な「郵便配達」に例えてイメージしてみましょう。
あなたがネットショッピングでどうしても欲しかった限定グッズを注文したとします。
1. あなた(クライアント)は、郵便局の窓口(ALB)へ注文書を託します。
2. 郵便局の窓口(ALB)は、その注文書を奥の倉庫にいる担当スタッフ(バックエンドのEC2やコンテナ)へ転送します。
3. 倉庫のスタッフは、巨大な棚の奥から商品を探し出そうとしますが……大人気商品のせいで在庫の山が崩れ、なかなか見つかりません!
4. 郵便局の窓口には「一定時間(待機時間)が過ぎたら、お客さんに『今ちょっと混み合っていて見つかりません』と伝えて窓口を閉めなさい」という厳格なルールがあります。
5. スタッフからの返事が一向に来ないまま制限時間が来てしまったため、窓口の担当者はあなたにこう告げます。「すみません、時間切れです!」
これが、504 Gateway Timeout の正体です。
つまり、「入り口のロードバランサー(ALB)は元気だけど、奥で控えているバックエンドのサーバーが、時間内に仕事を終わらせて返事をしてくれなかった状態」を指しています。ネットワークが完全に切断されたわけではなく、「待ちくたびれてタイムアウトした」というのがポイントですよ。
—
ALBの「アイドルタイムアウト」という厳格なルール
ALBには、バックエンドからの返事をどれくらい待ち続けるかという「アイドルタイムアウト(Idle Timeout)」という設定がデフォルトで備わっています。
このタイムアウト時間の初期値は、なんと 60秒 に設定されています。
「60秒もあれば十分でしょ!」と思いますよね。普段のシンプルなWebサイトならその通りです。しかし、次のような重たい処理を行うシステムでは、この60秒という壁がなかなかに高いハードルになってきます。
- データベースから何万件もの膨大なデータを集計してレポートを作る処理
- 外部の別システム(決済APIやAIサービスなど)を呼び出し、その返事を待っている間に時間がかかっている処理
- 巨大なファイルのアップロードや、画像・動画のサーバー側での変換処理
バックエンドのサーバーで「うーん、うーん」と頑張って処理をしている最中に、ALB側のタイマーが 60 秒を指してしまうと、サーバーが頑張って作っていた途中経過を無視して、ALBは無情にもクライアントへ 504 エラーを返してしまうのです。なんとも切ないすれ違いですよね。
—
現場で使える!タイムアウト設定のチューニング手法
それでは、このもどかしい 504 エラーを防ぐためにはどうすればよいでしょうか?
アプローチとしては大きく分けて2つあります。
1. ALBのアイドルタイムアウトの時間を延ばす(力技ですが確実です)
2. バックエンド側の処理を高速化する・非同期にする(根本的な解決を目指します)
今回は、インフラエンジニアとして真っ先に対処できる「1. ALBのアイドルタイムアウトの変更手順」を、AWS CLIとTerraformのコード例を交えて見ていきましょう!
方法A: AWS CLIでサクッと変更する
もし急ぎの検証や一時的な対応が必要な場合は、AWS CLIを使ってターゲットグループが紐づくロードバランサー(正確にはロードバランサーの属性)のタイムアウト値を変更できます。
以下のコマンドでは、タイムアウト時間をデフォルトの60秒から 120秒(2分) に引き上げています。
# ロードバランサーのアイドルタイムアウトを120秒に変更するコマンド
aws elbv2 modify-load-balancer-attributes \
--load-balancer-arn arn:aws:elasticloadbalancing:ap-northeast-1:123456789012:loadbalancer/app/my-web-alb/1234567890abcdef \
--attributes Key=idle_timeout.timeout_seconds,Value=120
*※注意:タイムアウトをむやみに長くしすぎると、レスポンスを返さない壊れたサーバーに対してALBがいつまでもコネクションを保持し続け、リソース(接続数上限)を圧迫する原因になります。必要な分だけ、適切に伸ばすのがプロの技です!*
方法B: Terraformでコードとして管理する
本番環境のインフラをコード(IaC)で管理している場合は、Terraformの aws_lb リソース内で設定するのがスマートです。
# ALB(Application Load Balancer)の定義
resource "aws_lb" "main" {
name = "my-app-lb"
internal = false
load_balancer_type = "application"
security_groups = [aws_security_group.alb.id]
subnets = aws_subnet.public[*].id
# ここでアイドルタイムアウトを90秒に指定(デフォルトの60秒から延長)
idle_timeout = 90
tags = {
Environment = "production"
Project = "awesome-web-app"
}
}
このようにコードとして明文化しておくことで、チームメンバー全員が「なぜこのタイムアウト値になっているのか」を後から迷わず確認できるようになります。
—
SREからのアドバイス:タイムアウトを延ばす「その前に」
最後に、現役のSREとして一つだけ現場の知見をシェアさせてください。
504 エラーが出たときに、「じゃあタイムアウトを300秒(5分)に延ばせば解決だ!」と安易に設定をいじるのは少し危険です。なぜなら、ユーザーがWebブラウザの画面を開いたまま5分間も待たされる体験は、UX(ユーザー体験)の観点から見ると決して褒められたものではないからです。
タイムアウトの数値をいじるのと並行して、以下のような設計上のアプローチも検討してみてくださいね。
- 重たい処理は「裏でこっそり(非同期)」やる:
ユーザーからのリクエストを受け付けたら「受け付けました!処理が終わったらメールでお知らせします」と即座に返事を返し、実際の重たい処理は裏のキュー(Amazon SQSやCeleryなど)に流してバックグラウンドで実行する。
- CloudWatchメトリクスを監視する:
HTTPCode_Target_5XX_Count や TargetResponseTime のメトリクスを監視し、「どの時間帯に、どのエンドポイントで処理が遅延しているのか」をあらかじめグラフで可視化しておく。
—
まとめ
今回は、ALBにおけるHTTPステータスコード 504 (Gateway Timeout) の発生原因と、アイドルタイムアウトの調整手法について解説しました。
- 504エラーの正体: バックエンドのサーバーが、ALBの待ち時間(デフォルト60秒)以内に返事を返せなかった状態。
- 解決の第一歩: ALBの
idle_timeoutパラメーターを調整して、システムの特性に合わせた待ち時間にカスタマイズする。 - 運用のコツ: 単に時間を延ばすだけでなく、ユーザー体験やバックエンドの非同期化も視野に入れてアーキテクチャを磨き上げる。
インフラやネットワークの世界は、最初は専門用語が多くて難しく感じるかもしれませんが、こうして一つひとつの挙動を身近なものに例えていくと、パケットや設定値の向こう側で動くシステムがぐっと身近に感じられるはずです。
皆さんのクラウドライフが、エラーの少ない快適なものになりますように。それではまた別の記事でお会いしましょう!
コメント