503 Service Unavailable の原因と対策 — 原理から現場で使える実践ガイド

503 Service Unavailable(サービス利用不可)とは

HTTP ステータスコードの 503 は「Service Unavailable」を意味し、サーバが一時的にリクエストを処理できないことを示します。RFC 7231 の定義では、サーバは一時的な過負荷やメンテナンスのためにリクエストを拒否しているが、将来の再試行で復帰する可能性があるとされています。503 はクライアント側の誤りではなく、サーバ側の一時的な状態を表すサーバエラー(5xx)です。

重要な点は 503 が「恒久的な失敗」を示すものではないということです。通常、適切な対応により復帰が期待され、場合によっては Retry-After ヘッダで再試行のタイミングを伝達できます。

503 が発生する主な原因

  • サーバの過負荷: CPU、メモリ、スレッド、コネクション数の枯渇やイベントループのブロッキング。
  • メンテナンスモード: 意図的にサービスを停止している(デプロイやDBマイグレーション等)。
  • 上流(アップストリーム)サービスの障害: マイクロサービス構成でバックエンドやDBが応答しない場合、リバースプロキシやゲートウェイが 503 を返すことがある。
  • リバースプロキシ/ロードバランサの設定: ヘルスチェック失敗によりターゲットが切り離され、処理可能なサーバが無くなる。
  • リソース制限やファイルディスクリプタ不足: OS レベルの制限が原因で新たな接続を受けられない。
  • DDoSやスパイクトラフィック: 外部からの大量リクエストにより正規ユーザ向けのサービスが枯渇。

503 と他の 5xx ステータスの違い

よく混同される 502 Bad Gateway や 504 Gateway Timeout との違いを押さえましょう。502 はゲートウェイやプロキシが受け取った上流サーバの不正な応答(不正なプロトコル等)を示し、504 は上流への接続がタイムアウトしたことを示します。503 は主に「サービスが一時的に利用不可」であり、上流の一時的な過負荷や意図的な停止を示す点が特徴です。

Retry-After ヘッダの使い方

503 とともに Retry-After ヘッダを返すと、クライアントに再試行までの推奨待機時間を伝えられます。値は秒数(例: "120")か、HTTP-date(例: "Wed, 21 Oct 2015 07:28:00 GMT")のいずれかです。長時間のメンテナンスやスケジュール済みのダウンタイムでは有用ですが、短時間の自動リトライを期待させすぎるとクライアント側の再試行がトラフィックを増やし問題を悪化させるため注意が必要です。

現場での調査・診断フロー

503 が発生したときの典型的な調査手順を示します。

  • 再現性の確認: 特定のエンドポイント・時間帯だけ発生するかを確認。
  • ログの確認: アプリケーションサーバ、リバースプロキシ(例: Nginx、HAProxy)、ロードバランサのエラーログやアクセスログを時系列で突き合わせる。
  • メトリクスの確認: CPU/メモリ、コネクション数、スレッドプール使用率、キュー長、GC ログなど。
  • ヘルスチェックと上流サービス: バックエンドや DB のヘルス状態、タイムアウト発生の有無を確認。タイムアウトや接続拒否が頻発するとリバースプロキシが 503 を返すことがある。
  • OS レベルの確認: file descriptor やネットワークソケットの枯渇、ulimit 設定。
  • 外部要因の確認: DDoS、CDN 側の問題、外部 API の遅延。

実装・設定上のポイント(例)

代表的なサーバでの取り扱い方を概説します。

  • Nginx: アプリがメンテナンス中の際に一時的に 503 を返すために "return 503" を使ったり、アップストリームが枯渇した際にエラーページを出す設定が可能。proxy_read_timeout や proxy_connect_timeout を適切に設定し、ヘルスチェックと連携することが重要。
  • Apache: mod_status や設定で MaxRequestWorkers を調整し、閾値を超えた際にリクエストを拒否することがある。KeepAlive やスレッドプールの設定が影響する。
  • ロードバランサ/HAProxy: ヘルスチェック失敗でバックエンドが切り離されると利用可能ノードが不足し 503 が発生する。timeout、maxconn、queue の監視が重要。
  • CDN/Edge: オリジンの応答が悪いとエッジが 503 を返す場合がある。CDN のキャッシュ設定やオリジンフェイルオーバーの設定を確認する。

対策とベストプラクティス

503 を減らし、発生時の影響を最小化するための実務的対策です。

  • オートスケールと容量計画: 一時的なトラフィック増に対応するためのスケーリング(水平スケール)とレート制限の組み合わせ。
  • グレースフルシャットダウン: デプロイ時に新規接続を受け付けないフェーズと、既存リクエストの処理完了を待つ仕組み。
  • キャッシュとスタレートラフィック許容: CDN やアプリ側で stale-while-revalidate を使い、上流が一時不調でも古いレスポンスを返して可用性を維持。
  • バックプレッシャとキュー: リクエスト増に直接耐えられない場合、内部キューで平滑化。キューが溢れる前に適切に 503 を返す設計(ファストフェイル)も重要。
  • サーキットブレーカー: 上流失敗を検知したら短時間で遮断し、状況が回復したら段階的に再開する。
  • 明示的なメンテナンスモード: 意図的な停止時に 503 と Retry-After を返してユーザに再試行タイミングを伝える。
  • 監視と自動化: アラート、ランブック、オートリカバリの仕組み。503 の増加はサービスの重大な警告指標。

UX とクライアント側の振る舞い

ユーザ体験を考えると、503 発生時のページやレスポンスを工夫することで不満を軽減できます。具体的には簡潔で誠実なエラーメッセージ、推定復旧時間やステータスページへのリンクを表示することが有効です。API クライアント向けには Retry-After を尊重した指数バックオフを推奨します(短時間で頻繁なリトライは逆効果)。

セキュリティと攻撃対策

頻発する 503 は DDoS の兆候であることがあります。WAF、レートリミット、IP レピュテーション、CDN のセキュリティ機能を活用し、異常トラフィックを早期にブロックすることが重要です。また、内部のリソース不足が原因である場合は、最小権限・分離設計で一部分の障害が全体に波及しないようにします。

現場で使えるチェックリスト

  • ログ: 503 が発生したタイムスタンプ、クライアント IP、リクエストパスを特定
  • メトリクス: 同時接続数、エラーレート、スレッド/プロセス数、メモリ使用率を確認
  • ヘルスチェック: バックエンドの応答性を確認
  • リトライポリシー: クライアントが適切なバックオフを行っているか
  • インフラ: オートスケールやロードバランサの構成を確認

まとめ

503 Service Unavailable は「一時的なサービス不可」を示す重要なステータスコードで、発生要因は多岐に渡ります。正しい診断はログ・メトリクス・ヘルスチェックの組み合わせで行い、オートスケール、キャッシュ、サーキットブレーカー、グレースフルシャットダウンなどの対策を組み合わせることで影響を最小化できます。ユーザ体験を損なわないために、明確なメッセージと再試行ポリシー(Retry-After)の提示も忘れないでください。

参考文献