MeWrite Docs

HTTP 502: Bad Gateway

プロキシサーバーがバックエンドから無効な応答を受け取った場合のエラー

概要

プロキシサーバーやロードバランサーが、バックエンドサーバーから無効な応答を受け取った場合に発生するエラーです。

エラーメッセージ

502 Bad Gateway

または

nginx: upstream prematurely closed connection

原因

  1. バックエンドダウン: アプリケーションサーバーが停止
  2. タイムアウト: バックエンドの応答が遅い
  3. リソース不足: メモリやCPUの枯渇
  4. 設定ミス: プロキシ設定の誤り

解決策

1. バックエンドの状態確認

1
2
3
4
5
6
7
8
9
# プロセス確認
ps aux | grep node
ps aux | grep python

# ログ確認
tail -f /var/log/myapp/error.log

# Docker ログ
docker logs -f myapp

2. Nginx の設定

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
upstream backend {
    server 127.0.0.1:3000;
    keepalive 32;
}

server {
    location / {
        proxy_pass http://backend;

        # タイムアウト設定
        proxy_connect_timeout 60s;
        proxy_send_timeout 60s;
        proxy_read_timeout 60s;

        # バッファ設定
        proxy_buffer_size 128k;
        proxy_buffers 4 256k;
        proxy_busy_buffers_size 256k;

        # エラー時の動作
        proxy_next_upstream error timeout http_502;
    }
}

3. ヘルスチェック

1
2
3
4
5
6
7
upstream backend {
    server 127.0.0.1:3000;
    server 127.0.0.1:3001 backup;

    # ヘルスチェック(Nginx Plus)
    health_check interval=5s fails=3 passes=2;
}

4. AWS ALB の設定

1
2
3
4
5
6
7
8
# ターゲットグループのヘルスチェック
aws elbv2 modify-target-group \
  --target-group-arn arn:aws:elasticloadbalancing:... \
  --health-check-path /health \
  --health-check-interval-seconds 30 \
  --health-check-timeout-seconds 5 \
  --healthy-threshold-count 2 \
  --unhealthy-threshold-count 3

5. リソース監視

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# メモリ使用状況
free -m

# CPU使用状況
top -bn1 | head -20

# ディスク使用状況
df -h

# プロセスのメモリ使用
ps aux --sort=-%mem | head -10

6. 接続数の確認

1
2
3
4
5
6
7
8
# 確立された接続数
netstat -an | grep ESTABLISHED | wc -l

# 接続待ちの数
netstat -an | grep LISTEN

# TIME_WAIT の数
netstat -an | grep TIME_WAIT | wc -l

7. Node.js のクラスタリング

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
const cluster = require('cluster');
const numCPUs = require('os').cpus().length;

if (cluster.isMaster) {
  for (let i = 0; i < numCPUs; i++) {
    cluster.fork();
  }

  cluster.on('exit', (worker, code, signal) => {
    console.log(`Worker ${worker.process.pid} died`);
    cluster.fork();  // 再起動
  });
} else {
  require('./app');
}

8. PM2 でのプロセス管理

1
2
3
4
5
6
7
8
9
# PM2 で起動
pm2 start app.js -i max  # CPU数分のインスタンス

# 状態確認
pm2 status
pm2 logs

# 再起動
pm2 restart app

9. Docker の再起動ポリシー

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# docker-compose.yml
services:
  app:
    restart: unless-stopped
    deploy:
      resources:
        limits:
          memory: 512M
        reservations:
          memory: 256M

10. アプリケーションのグレースフルシャットダウン

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
// Node.js
const server = app.listen(3000);

process.on('SIGTERM', () => {
  console.log('SIGTERM received, shutting down gracefully');

  server.close(() => {
    console.log('HTTP server closed');

    // DB接続を閉じる
    db.close()
      .then(() => process.exit(0))
      .catch(() => process.exit(1));
  });

  // 強制終了タイマー
  setTimeout(() => {
    console.error('Forcing shutdown');
    process.exit(1);
  }, 30000);
});

よくある間違い

  • バックエンドのポート番号の誤り
  • タイムアウト値がバックエンドの処理時間より短い
  • ヘルスチェックエンドポイントがない
  • メモリリークによるクラッシュ

HTTP の他のエラー

最終更新: 2025-12-09