MeWrite Docs

HTTP 503: Service Unavailable

サービス利用不可エラーの解決方法

概要

サーバーが一時的にリクエストを処理できない場合に返されるHTTPステータスコードです。

エラーメッセージ

HTTP/1.1 503 Service Unavailable
Retry-After: 120

原因

  1. サーバー過負荷: リソース不足
  2. メンテナンス中: 計画的なダウンタイム
  3. 依存サービス障害: バックエンドサービスがダウン
  4. ヘルスチェック失敗: ロードバランサーがサーバーを切り離し

解決策

1. サーバー側の対応

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
// ヘルスチェックエンドポイント
app.get('/health', async (req, res) => {
  try {
    await db.query('SELECT 1');
    await redis.ping();
    res.status(200).json({ status: 'healthy' });
  } catch (err) {
    res.status(503).json({ status: 'unhealthy', error: err.message });
  }
});

2. グレースフルシャットダウン

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
let isShuttingDown = false;

app.use((req, res, next) => {
  if (isShuttingDown) {
    return res.status(503).json({
      error: 'Service is shutting down'
    });
  }
  next();
});

process.on('SIGTERM', () => {
  isShuttingDown = true;
  server.close(() => {
    process.exit(0);
  });
});

3. クライアント側リトライ

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
async function fetchWithBackoff(url, maxRetries = 3) {
  for (let i = 0; i < maxRetries; i++) {
    const response = await fetch(url);

    if (response.status !== 503) {
      return response;
    }

    const retryAfter = response.headers.get('Retry-After');
    const delay = retryAfter ? parseInt(retryAfter) * 1000 : Math.pow(2, i) * 1000;
    await sleep(delay);
  }

  throw new Error('Service unavailable after retries');
}

4. サーキットブレーカー

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
import CircuitBreaker from 'opossum';

const breaker = new CircuitBreaker(fetch, {
  timeout: 3000,
  errorThresholdPercentage: 50,
  resetTimeout: 30000
});

breaker.on('open', () => console.log('Circuit opened'));
breaker.on('halfOpen', () => console.log('Circuit half-open'));
breaker.on('close', () => console.log('Circuit closed'));

await breaker.fire(url);

よくある間違い

  • リトライなしでエラー表示
  • サーキットブレーカーなしで障害伝播

HTTP の他のエラー

最終更新: 2025-12-09