徹底解説:502 Proxy Error(Bad Gateway)の原因と対処法 — サーバー/リバースプロキシ/クラウド環境別トラブルシューティング

502 Proxy Error(Bad Gateway)とは

HTTPステータスコード502は「Bad Gateway」として定義され、リバースプロキシやゲートウェイが上流のサーバー(バックエンド)から無効な応答を受け取ったときに返されます。一般的に“502 Proxy Error”と表示される場面は、Nginx、HAProxy、Varnish、CDN(Cloudflareなど)、あるいはクラウドのロードバランサ(AWS ALB/ELB等)がフロントエンドとして動作し、バックエンドのアプリケーションやAPIが期待するHTTPヘッダやステータス行を返さない場合などです。

502と他の関連ステータスコードとの違い

  • 500 Internal Server Error:フロントもバックエンドもサーバ内部の処理エラー。

  • 502 Bad Gateway:ゲートウェイ/プロキシが上流から「無効な」応答を受け取った。

  • 503 Service Unavailable:サービスが一時利用不可(メンテナンスや負荷過剰)。

  • 504 Gateway Timeout:ゲートウェイが上流からの応答を待ち切れずタイムアウト。

発生し得る主な原因

  • バックエンドプロセスがクラッシュ、停止している(例:PHP-FPM、Gunicorn、uWSGI、Node.js等)。

  • バックエンドが接続拒否(Connection refused)やソケット未生成(unix socketのパス誤り)。

  • バックエンドが不正なHTTPヘッダや空の応答を返している(プロトコルミスマッチやアプリケーション例外)。

  • リバースプロキシ側のバッファ不足や設定ミス(proxy_buffer_sizeやfastcgi_buffersなど)。

  • ロードバランサやCDNのヘルスチェック失敗、あるいはDNSの誤設定で誤った上流に接続している。

  • SSL/TLSハンドシェイクの失敗(SNI指定の欠落、証明書問題など)やプロキシ間の暗号化設定不一致。

  • ファイアウォール/ネットワークACL、iptables等で通信が遮断されている。

  • 過負荷によるプロセス応答不能(GC停滞、接続プール枯渇、メモリ不足など)。

よく見るログの例と意味

  • Nginx: "connect() to 127.0.0.1:9000 failed (111: Connection refused) while connecting to upstream" → バックエンドがリッスンしていない。

  • Nginx: "upstream prematurely closed connection while reading response header from upstream" → バックエンドがヘッダ送出前に切断。

  • Nginx: "upstream sent invalid header" → バックエンドがHTTPヘッダとして不正なデータを返した。

  • HAProxy: frontend/backendのログで502が出る場合は、バックエンドプロセスの終了・不正応答・初期化失敗を疑う。

診断のための実作業チェックリスト

  • フロントエンドのエラーログとアクセスログを確認(例: /var/log/nginx/error.log, access.log)。

  • バックエンドのログ(アプリの標準出力、systemd/journal、php-fpm/error.log等)を確認する。

  • バックエンドに直接リクエストしてみる。curl -v http://127.0.0.1:9000/ 等でヘッダ・ステータスを確認。

  • ソケット/ポートの状態確認:ss -ltnp や netstat -plnt でプロセスがリッスンしているか。

  • TLS問題の切り分け:openssl s_client -connect origin:443 -servername example.com でハンドシェイクを確認。

  • DNS解決の確認:dig +short example.com / /etc/hostsの誤記載がないか。

  • ネットワーク・ファイアウォール確認:iptables -L、セキュリティグループ、クラウドACL。

  • リソース監視:top/htop、ps aux、dmesg、ページングやOOMの兆候確認。

  • プロセス再起動で一時的に直るかを確認し、根本原因のヒープログラムやコネクションプールの枯渇を調査する。

短期対処(現場で素早く行うこと)

  • サービスの状態を確認して停止していたら再起動(systemctl restart php-fpm, systemctl restart gunicorn など)。

  • 接続先のソケットパスやポート設定の誤りを修正(unix:/var/run/php-fpm.sock と proxy_pass の整合性等)。

  • プロキシとバックエンドのタイムアウト値を一時的に延長して様子を見る(proxy_connect_timeout, proxy_read_timeout等)。

  • バッファ関連でエラー出る場合は proxy_buffer_size や fastcgi_buffers を調整。

  • クラウドやCDN利用時は、オリジンのヘルスチェック設定と実際のポート/パスが一致しているか確認。

中長期的な対策(根本原因の排除と再発防止)

  • アプリケーションのログを分析して例外やメモリリークを修正。JVM/Node/PHPのGCやワーカー設定を適切化。

  • コネクションプールやワーカ数の見直し(PHP-FPMのpm.max_children、Gunicornのworkers等)。

  • ヘルスチェックと自動リカバリを整備(systemdのRestart=on-failure、KubernetesのLiveness/Readiness probes)。

  • 冗長化とロードバランシングで単一障害点を排除、オートスケールを導入して負荷時の回復力を確保。

  • 監視とアラート整備:レスポンスタイム、エラーレート、プロセス数、接続数、ログの定量的モニタリング(Prometheus/Grafana等)。

  • CI/CDでの構成管理とステージング環境を整え、設定ミスやエンドポイント変更を本番に直接反映しない運用にする。

Nginx や PHP-FPM、uWSGI等でよくある具体的ミスと対処例

  • proxy_pass のURLにスラッシュの付け忘れで期待するパスが変わるケース。設定ファイルのproxy_passの書き方を再確認する。

  • unixソケットパスが異なる:nginxが /var/run/php/php7.4-fpm.sock を参照しているが、実際は別パス。socketファイル存在確認と権限確認を行う。

  • php-fpmの子プロセス上限(pm.max_children)が低すぎて接続が捌けずエラーになる場合は適正化。

  • uWSGIやGunicornでプロセスがシグナル等で落ちる場合はSupervisor/systemdの自動復旧設定を入れる。

クラウド/CDN固有の注意点

  • AWS ELB/ALBの502:通常はバックエンドから無効な応答が返っているか、ヘルスチェックが不適切。

  • Cloudflareの502:Cloudflareがオリジンに接続できたが不正な応答を受け取った場合に発生。Cloudflareは502, 521, 522等複数のコードで原因を区別するため、公式ドキュメントを参照。

  • CDNを導入している場合は、一時的にプロキシをバイパスして直接オリジンへアクセスし、問題の切り分けをする。

運用上のベストプラクティス

  • ロギングに相関ID(X-Request-ID等)を付与してフロント→バックエンドのログを追跡しやすくする。

  • 自動復旧(プロセス監視・再起動)と段階的リリース(カナリア、ブルーグリーン)で障害影響を最小化。

  • SLO/SLIを定義し、502発生時のビジネス影響を定量化して適切なリソース投資を行う。

  • 定期的な負荷試験と障害注入(Chaos Engineering)で、502原因になり得る箇所を事前に発見する。

まとめ

502 Proxy Errorは「フロントのプロキシが上流から『無効な』応答を受け取った」ことを示すエラーであり、原因は多岐に渡ります。ログを注意深く解析し、フロントエンド→バックエンド→ネットワークの順に切り分けを行うことが肝要です。短期的にはサービス再起動やタイムアウト調整、中長期的にはリソース/ワーカー設定・冗長化・監視整備といった対策を組み合わせることで再発を防げます。

参考文献