サーバーが「沈黙」するとき:HTTP 5xxエラーとの付き合い方とインフラ設計の鉄則
ネットワークエンジニアとして現場に立っていると、深夜の呼び出し通知ほど心拍数を上げるものはありません。特に「5xx系エラー」の検知は、我々インフラ屋にとっての宣戦布告です。
4xxエラーが「クライアントのお門違い(リクエストの間違い)」であるのに対し、5xxエラーは「我々が管理するサーバー側の敗北」を意味します。今日は、HTTP/1.1の仕様を紐解きつつ、この「サーバーからの無慈悲な拒絶」をどう解釈し、どう切り分けるべきか、実務的な視点で深掘りしていきましょう。
—
1. 5xxエラーの正体:RFCが語る「責任の所在」
HTTPステータスコードの500番台は、RFC 7231で「Server Error」と定義されています。クライアント(ブラウザやAPI利用者)が正しいリクエストを投げたにもかかわらず、サーバーが「処理を完了できない」と判断した状態です。
特に現場で頻出する3つを整理します。
- 500 Internal Server Error: サーバー内部で予期せぬ例外が発生。コードのバグや、DB接続断など、「何が起きたかサーバー自身も混乱している」状態。
- 502 Bad Gateway: 上流のプロキシ(Nginxなど)が、後続のアプリケーションサーバーから不正なレスポンスを受け取った状態。
- 503 Service Unavailable: サーバーが過負荷、またはメンテナンス中。一番「誠実」なエラーです。
- 504 Gateway Timeout: 上流のプロキシが、バックエンドからの応答を待ちきれずにタイムアウトした状態。
—
2. 実務的なデバッグの第一歩:通信フローを可視化する
インフラサイドでは、パケットがどこで止まっているかを特定することが全てです。curlを使って、まずはヘッドレスな状態で何が起きているかを確認しましょう。
-v オプションで、どのステップでエラーが返されているかを確認
サーバーのレスポンスヘッダー(ServerやX-Cacheなど)にヒントが隠れていることが多い
curl -Iv https://api.example.com/v1/resource
もし、あなたがバックエンドエンジニアなら、Fetch APIでこのエラーをキャッチし、ログを構造化しておく必要があります。
// Fetch APIでのエラーハンドリング例
fetch(‘https://api.example.com/data’)
.then(response => {
if (!response.ok) {
// 5xxエラーの場合、ステータスコードをログに記録して監視ツールへ飛ばす
console.error(`サーバーエラー発生: ${response.status}`);
throw new Error(`Server returned ${response.status}`);
}
return response.json();
})
.catch(err => console.error(‘通信失敗:’, err));
—
3. インフラ側で「5xx」をハンドリングする(Nginxの視点)
ロードバランサーやリバースプロキシの役割は、単なる転送だけではありません。バックエンドが死んでいる時に、ユーザーに無機質なエラー画面を見せない「優しさ」も必要です。
以下は、Nginxで502/503/504をハンドリングし、カスタムエラーページを表示する設定例です。
nginx.conf の設定例
location / {
proxy_pass http://backend_cluster;
# バックエンドがダウンしている時の挙動を制御
proxy_next_upstream error timeout http_502 http_503 http_504;
# 5xxエラーを検知したら、静的なメンテナンスページに飛ばす
error_page 502 503 504 /custom_50x.html;
}
location = /custom_50x.html {
root /usr/share/nginx/html; # サーバー負荷が高い時でも返せる軽量なHTML
}
—
4. 現場でトラブルを早期解決するための3つのTips
1. 「502」と「504」の区別に命をかける:
- 502は「バックエンドのプロセスが死んでいるか、ソケットが閉じている」可能性大。即座にプロセス監視(systemdやKubernetesのLiveness Probe)を確認せよ。
- 504は「バックエンドが重すぎて応答に時間がかかっている」可能性大。DBのクエリ実行計画(Slow Query)を疑え。
2. ログの共通IDを付与する:
- リクエストヘッダーに `X-Request-ID` を付与し、ロードバランサーからアプリケーション、DBログまで一気通貫で追えるようにする。これが無いと障害対応の時間は倍かかります。
3. フェイルオーバーの自動化を過信しない:
- 自動復旧(オートスケーリングなど)は強力ですが、原因が「DBへの負荷集中」である場合、オートスケーリングでサーバーを増やしても、DBがトドメを刺されて全滅します。「何がボトルネックか」を特定しない自動化は、単なる延命処置であることを忘れないでください。
—
最後に:エラーは「教訓」である
5xxエラーは、システムにとっての「痛み」です。しかし、この痛みがあるからこそ、我々はバックエンドの堅牢性を高め、タイムアウト設定を最適化し、より強靭なインフラを構築できます。
エラーログを眺める時、「運が悪い」と思わず、「システムがどこで限界を迎えたのか」を冷静に分析してみてください。その積み重ねこそが、あなたを一流のネットワークアーキテクトへと押し上げる唯一の道です。
さあ、次はどのログを解析しましょうか?
コメント