502 Bad Gateway
502が出たらまず上流アプリの生死を見る。原因の切り分け表と診断コマンドで、リバースプロキシと上流のどちらが壊れたかを最短で特定し復旧できる。
- 502はリバースプロキシ/LBが上流から有効な応答を受け取れなかったことを示す。壊れているのはプロキシではなく上流アプリか両者の接続で、多くは上流のクラッシュ・過負荷・タイムアウトが原因。
- 診断は上流プロセスの生死確認→プロキシのエラーログ(nginx なら upstream 行)→上流への直接アクセスの順。504(上流の応答が遅すぎる)や503(プロキシ自身が処理不能)との違いで原因層を絞る。
- 解決は上流の再起動・リソース増強・タイムアウトとワーカー数の整合。予防はヘルスチェック、graceful restart、keepalive とプールの見直しで再発を断つ。
一言でいうと(このエラーが何を意味するか)
502 Bad Gateway は、ゲートウェイまたはプロキシとして動作するサーバーが、上流(upstream)サーバーへリクエストを転送したものの、有効な HTTP 応答を受け取れなかったことを示すステータスコードです。RFC 9110 では「上流サーバーから無効な応答を受け取った」と定義されます。
ここで決定的に重要なのは、502 を返しているのはクライアントに一番近いリバースプロキシ/ロードバランサであり、実際に壊れているのはその背後の上流アプリ、または両者をつなぐ接続だという点です。nginx や ALB、Cloudflare が「502」を出しても、それらのソフト自体は正常に動いています。エラーページを出せている時点でプロキシは生きており、問題は上流にあります。
リバースプロキシから見て、リクエストを実際に処理させるバックエンドを上流(upstream / backend / origin)と呼びます。具体的には PHP-FPM、Gunicorn/uWSGI、Node.js、Puma、あるいはさらに奥の別ロードバランサなどです。502 の調査は常に「プロキシは正常、上流を疑う」から始めます。
横にスクロール
よくある原因(複数を具体的に、頻度順)
- 上流アプリのプロセスがクラッシュ/未起動: 最も多い原因。デプロイ失敗、OOM Killer による強制終了、設定ミスによる起動失敗などでアプリが listen していない、または途中で落ちる。プロキシは接続先へつなげず(Connection refused)502 を返す。
- 上流の過負荷によるワーカー枯渇: リクエスト数がワーカー/プロセス数を超え、新規接続がバックログ上限(listen backlog)を超えて拒否される。負荷スパイク時に断続的な 502 として現れる。
- 上流の応答が途中で切れる・不正: アプリが接続を確立した後にセグメンテーション違反やタイムアウトで接続を早期クローズし、ヘッダを返し終える前に切断する。nginx はこれを
upstream prematurely closed connectionとして 502 にする。 - プロキシ〜上流間のタイムアウト(接続確立の失敗):
proxy_connect_timeout内に TCP 接続を確立できない場合。ネットワーク分断、上流のヘルス悪化、ファイアウォールやセキュリティグループの誤設定で発生。なお応答本文が遅いことによるタイムアウトは通常 504。 - 上流が返すヘッダの破損・巨大化: ヘッダサイズがプロキシのバッファ上限を超える、あるいは不正なステータス行を返す。
upstream sent too big headerなどが典型。 - keepalive の不整合: 上流がアイドル接続を先に閉じたのに、プロキシが同じ接続を再利用しようとして失敗する競合。トラフィックが少ない時間帯に散発する 502 の典型パターン。
診断の手順(切り分け方・見るべきログ/コマンド)
原因層を上から潰していきます。順番が重要です。
手順1: 上流プロセスの生死を確認する。
# 上流が想定ポートで listen しているか
ss -ltnp | grep -E ':(8000|9000|3000)'
# プロセスが動いているか(例: gunicorn / php-fpm)
systemctl status gunicorn
# 直近でOOM Killerに殺されていないか
dmesg -T | grep -i 'killed process'
手順2: プロキシのエラーログで上流エラーの種別を読む。 nginx なら error.log に理由が明記されます。ここで原因の 8 割が判明します。
tail -n 100 /var/log/nginx/error.log | grep -i upstream
# 代表的な出力と意味:
# connect() failed (111: Connection refused) -> 上流が起動していない/落ちている
# upstream prematurely closed connection -> 上流が応答途中で切断(クラッシュ等)
# upstream timed out (110) while connecting -> 接続確立に失敗(→504ではなく502側)
# upstream sent too big header -> ヘッダがバッファ超過
手順3: 上流へ直接アクセスして層を切り分ける。 プロキシを介さず上流を叩き、正常応答が返るかを見ます。
# ローカルの上流に直接リクエスト(プロキシをバイパス)
curl -sv http://127.0.0.1:8000/healthz
ここで正常なら問題はプロキシ〜上流間(ネットワーク・タイムアウト・keepalive)に、異常なら上流アプリ自体にあります。ロードバランサ配下なら、ターゲットグループ/バックエンドのヘルスチェック状態も必ず確認します(AWS ALB なら Target health、GCP なら backend health)。
手順4: 503/504 と区別して原因層を確定する。 これが最短の切り分けです。
| コード | 意味 | 壊れている層 | 典型原因 |
|---|---|---|---|
| 502 | 上流から無効な応答 | 上流アプリ or 接続 | 上流のクラッシュ/早期切断/接続拒否 |
| 503 | サービス利用不可 | プロキシ or 上流の受付 | 上流ゼロ台/メンテ/レート制限、過負荷での意図的拒否 |
| 504 | 上流の応答が時間切れ | 上流の処理速度 | 上流は生きているが処理が遅い(read timeout 超過) |
要点は、502 は「返ってきた応答が壊れている」、504 は「そもそも返ってこない(遅すぎる)」、503 は「受け付ける先がない/わざと断っている」という違いです。504 が出るなら上流は生きていて遅いだけなので、調査対象はクエリ性能や外部 API 待ちに移ります。503 で上流台数がゼロなら、まずデプロイ/ヘルスチェック設定を疑います。
解決と予防(対処と再発防止)
即時の対処は原因層に対応します。
- 上流がクラッシュ/未起動: プロセスを再起動し、起動ログでエラーを確認する。OOM が原因ならメモリ上限やワーカー数を見直す。
- ワーカー枯渇: 一時的にワーカー/プロセス数を増やし、listen backlog を拡張する。根本的には水平スケールやオートスケールの閾値を調整する。
- タイムアウト系: 上流の処理時間の実態に合わせて
proxy_connect_timeoutなどを調整する。ただし値を延ばすのは対症療法で、遅い原因の除去が本筋。
再発防止では設定の整合を取ります。とくに keepalive 起因の散発 502 は、上流のアイドルタイムアウトをプロキシ側より長くするのが定石です。
upstream app {
server 127.0.0.1:8000;
keepalive 32; # プロキシ側で接続をプール
}
server {
location / {
proxy_pass http://app;
proxy_http_version 1.1; # keepalive には 1.1 が必須
proxy_set_header Connection "";
proxy_next_upstream error timeout http_502; # 502時は別の上流へ再試行
}
}
プロキシのタイムアウトだけ延ばしても、上流のワーカーが詰まったままなら 502/504 は解消しません。プロキシと上流でタイムアウトの上下関係を設計し(上流のアイドル > プロキシの keepalive、上流の処理制限 < プロキシの read timeout)、片方だけをいじらないことが再発防止の要です。
デプロイ時に一瞬 502 が出るのは、古いプロセスを止めてから新プロセスが listen するまでに隙間ができるためです。PHP-FPM / Gunicorn / systemd のリロードを graceful(既存接続を捌き切ってから切替)にし、ロードバランサのヘルスチェックが通ってから旧系を落とすローリング更新にすれば、ダウンタイムなしで切り替わります。
HTTP のステータスコード体系やプロキシの位置づけはWebを、TCP 接続確立・タイムアウトの原理はネットワークを、上流のオートスケールやローリングデプロイの設計はDevOpsを参照してください。
- 502 を返すのはプロキシ側で、故障しているのは上流アプリまたは接続。「プロキシは正常、上流を疑う」
- 502(応答が無効)/503(受付先なし・意図的拒否)/504(上流が遅く時間切れ)の切り分け
- nginx のログ
connect() failed (Connection refused)は上流未起動、prematurely closed connectionは早期切断 - keepalive 不整合による散発 502 は、上流のアイドルタイムアウトをプロキシより長く取ることで解消する
エラー辞典の記事ガイド
502 Bad Gatewayを実務で読む
TL;DRは入口です。実際に選ぶ・使う段階では、何を解決するか、何と比較するか、導入後にどこで詰まるかまで見る必要があります。
解決すること
HTTP
比較で見る軸
難易度: advanced / カテゴリ: エラー辞典 / タグ数: 6
導入後に効く点
診断は上流プロセスの生死確認→プロキシのエラーログ(nginx なら upstream 行)→上流への直接アクセスの順。504(上流の応答が遅すぎる)や503(プロキシ自身が処理不能)との違いで原因層を絞る。
先に潰すリスク
用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。
- 難易度
- advanced
- カテゴリ
- エラー辞典
- タグ数
- 6
判断チェックリスト
- 自社の用途が「HTTP / nginx」に近いか確認する。
- 強みである「502はリバースプロキシ/LBが上流から有効な応答を受け取れなかったことを示す。壊れているのはプロキシではなく上流アプリか両者の接続で、多くは上流のクラッシュ・過負荷・タイムアウトが原因。」が本当に評価軸になるか確認する。
- 注意点の「用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。」を運用で吸収できるか確認する。
- 公開値や仕様値は、対象プラン・対象機種・対象リージョンまで確認する。
- 既存システム、ID、ネットワーク、監視、バックアップとの接続方法を先に洗い出す。
- 小さく試してから、本番移行、権限設計、障害時手順、コスト監視を決める。