5xxの深淵:インフラアーキテクトが対峙する「沈黙するバックエンド」の正体
我々インフラエンジニアにとって、HTTP 5xx系ステータスコードは単なる「エラー」ではない。それは、クライアントとサーバーの間に横たわる、見えない断絶の悲鳴である。
HTTP/1.1の時代から続くこのプロトコルは、シンプルであるがゆえに、境界条件における挙動が極めてシビアだ。今日は、ロードバランサー(L7)とバックエンドの間で起きている「真実」を、パケットレベルの視点から紐解いていこう。
—
1. 502 Bad Gateway:TCPの「見えない断絶」
502は、ロードバランサーがバックエンドへの接続を試みたものの、期待した応答を得られなかった時に吐き出される。ここで重要なのは、「RSTパケット」の解釈だ。
バックエンドのアプリケーションがクラッシュし、カーネルがTCPコネクションを強制終了させる際、FINではなくRSTを投げてくることがある。ロードバランサー側でこのRSTを検知したとき、接続プール内のコネクションを即座に破棄できるかどうかが、その後のシステム全体の安定性を左右する。
現場で見るべきカーネルパラメータ
接続過多による一時的なキュー溢れを防ぐため、以下のチューニングは必須だ。
TCPの接続待ち行列の最大値を引き上げ、SYN Flood気味な状況を緩和する
sysctl -w net.core.somaxconn=65535
TCPコネクションの再利用を許可し、TIME_WAIT問題を回避
sysctl -w net.ipv4.tcp_tw_reuse=1
送信バッファと受信バッファの最適化(RTTが長い環境では特に重要)
sysctl -w net.core.rmem_max=16777216
sysctl -w net.core.wmem_max=16777216
—
2. 504 Gateway Timeout:RTTの罠とバックエンドの「死」
504が発生する原因の多くは、L7ロードバランサー(NginxやHAProxyなど)のタイムアウト設定と、バックエンドの処理時間の乖離にある。
ここでエンジニアが陥りがちな罠が、「TLSハンドシェイクのコスト」の過小評価だ。TLS 1.2以前では、ハンドシェイクだけで往復(RTT)回数が多く、これがバックエンドの応答時間に上乗せされる。TLS 1.3への移行は、単なるセキュリティ強化ではなく、RTTを削減し、504の発生を物理的に抑え込むための「インフラ高速化策」なのだ。
Nginxでのタイムアウト最適化例
バックエンドの処理が重い場合、単に時間を延ばすのではなく、どこで詰まっているかをトレースする設計が必要だ。
upstream設定でのタイムアウト調整
upstream backend_pool {
server 10.0.0.1:8080 fail_timeout=5s max_fails=3;
keepalive 32; # 接続の使い回しでTCPハンドシェイクを削減する
}
location / {
proxy_connect_timeout 2s; # バックエンドとの接続確立限界
proxy_read_timeout 10s; # 応答を待つ限界
proxy_send_timeout 10s; # 送信完了を待つ限界
proxy_next_upstream error timeout http_502 http_503 http_504; # 5xx発生時の再試行ロジック
}
—
3. 500 Internal Server Error:境界線の向こう側
500エラーはサーバーサイドのアプリケーションコードに起因することが大半だが、インフラ側から見れば「例外処理の漏れ」である。
ここで意識すべきは、「ヘッダー圧縮とパケットサイズ」だ。HTTP/1.1ではヘッダーはプレーンテキストであり、巨大なCookieやAuthorizationヘッダーがパケットのMTU(Maximum Transmission Unit)を超えると、IP断片化(Fragmentation)が発生する。これがファイアウォールやIDSでドロップされ、バックエンドがリクエストを受け取れずに500相当の不整合を起こすケースが稀にある。
- 対策: `TCP MSS Clamping` を適切に設定し、パケットがフラグメントされないように制御する。
- セキュリティ: `Content-Length` と `Transfer-Encoding` の両方が付与されたリクエストに対する、HTTP Request Smuggling攻撃のガードを意識すること。
—
4. 総括:システムを「堅牢」にするということ
5xxエラーを防ぐためには、以下の3点を徹底してほしい。
1. 可観測性(Observability)の確保: ログだけでなく、tcpdumpでSYN/ACKのタイミング、RSTの発生源を物理的に追跡できる環境を持つこと。
2. TCP/TLSの最適化: Keep-Aliveを適切に維持し、ハンドシェイクの回数を減らす。これはレイテンシの改善に直結する。
3. Graceful Shutdownの設計: バックエンドを再起動する際、既存のコネクションを即座に切断せず、L7と協調してトラフィックを逃がす仕組みを作ること。
ネットワークは常に嘘をつかない。パケットの挙動を読み解く力こそが、我々インフラアーキテクトが持つ最強の武器なのだ。さて、次はどのプロトコルの深淵を覗こうか。
コメント