[error] 3896#0: *1 upstream prematurely closed connection while reading response header from upstream

重い処理をすると「[error] 3896#0: *1 upstream prematurely closed connection while reading response header from upstream,」というエラーが出たので、考えられる解決策を紹介します。

実行環境は以下の通りです。

  • aws ec2 (t3.small)
  • nginx
  • django
  • gunicorn
  • mysql
  • load balancer
目次

エラーが起こる原因

[error] 3896#0: *1 upstream prematurely closed connection while reading response header from upstream というエラーは、主に Nginx が upstream(Gunicorn)からのレスポンスを受け取る前に接続が切断された 場合に発生します。これは、処理が重いために タイムアウトリソース不足 などが原因で起こることが多いです。

【解決策1】Nginx のタイムアウト設定を延長する

Nginx のデフォルトの proxy_read_timeout は 60 秒程度ですが、処理が重い場合はこれを延長することで解決する可能性があります。

server {
    location / {
        proxy_connect_timeout 300;
        proxy_send_timeout 300;
        proxy_read_timeout 300;
        send_timeout 300;
    }
}

設定変更後、Nginx を再起動してください。

sudo systemctl restart nginx

【解決策2】Gunicorn のタイムアウトを延長する

Gunicorn のデフォルトのタイムアウトは 30 秒です。これを長めに設定します。

gunicorn の起動オプションに --timeout 300 を追加します。

gunicorn --timeout 300 --workers 3 myproject.wsgi:application

または、gunicorn.service (systemd) に設定を追加:

[Service]
ExecStart=/path/to/venv/bin/gunicorn --timeout 300 --workers 3 myproject.wsgi:application

設定変更後、Gunicorn を再起動してください。

sudo systemctl daemon-reload
sudo systemctl restart gunicorn

【解決策3】Gunicorn のワーカー数を調整する

現在の t3.small (2vCPU, 2GB RAM) では、Gunicorn の ワーカー数が多すぎるとメモリ不足 になります。
適切なワーカー数の目安は:

ワーカー数 = (CPU コア数 × 2) + 1

t3.small (2 vCPU) なら 5ワーカーまで が適切です。

gunicorn --workers 5 myproject.wsgi:application

注意:
ワーカー数を増やしすぎると、逆に OOM (Out of Memory) でプロセスが落ちるため、慎重に設定してください。

【解決策4】Gunicorn を sync から gevent に変更

Gunicorn のデフォルトの sync ワーカー はリクエストごとにブロックされるため、処理が遅くなることがあります。
gevent を使うと 非同期処理 になり、パフォーマンスが改善する可能性があります。

pip install gunicorn gevent
gunicorn --worker-class gevent --workers 3 myproject.wsgi:application

【解決策5】Django のデータベースクエリを最適化する

重い処理の原因が データベースの負荷 の場合、以下を試してください。

  • クエリの最適化 (select_related, prefetch_related)
  • インデックスの追加 (EXPLAIN ANALYZE でボトルネックを特定)
  • MySQL の設定調整 (innodb_buffer_pool_size の増加)
  • Redis キャッシュの導入 (django-cacheopsdjango-redis)

【解決策6】AWS Load Balancer のタイムアウトを延長する

AWS の ALB/NLB のデフォルトのタイムアウトは 60 秒 です。
長時間処理が必要な場合は、 タイムアウトを 300 秒程度に設定 してください。

変更方法

AWS コンソール → EC2 → Load Balancer → 対象の ALB/NLB を選択
属性アイドルタイム300 に変更。

【解決策7】EC2 インスタンスタイプのアップグレード

t3.small (2vCPU, 2GB RAM) は負荷が高いとリソース不足になりやすいです。

アップグレードの選択肢

インスタンスvCPURAM用途
t3.small22GB現在の環境
t3.medium24GBメモリ増加
t3.large28GBさらに余裕

EC2 のリソースが不足していないか、以下のコマンドで確認してください。

top
free -m
df -h

CPU やメモリ使用率が高い場合、t3.medium 以上へアップグレードを検討してください。

【解決策8】ログの確認(エラーの詳細を特定)

どこでタイムアウトが発生しているか特定するために、以下のログを確認してください。

sudo tail -f /var/log/nginx/error.log
sudo journalctl -u gunicorn --no-pager | tail -n 50
sudo tail -f /var/log/mysql/error.log

まとめ

優先度対策
🔥 最優先① Nginx の proxy_read_timeout を増やす
優先② Gunicorn の timeout を増やす
優先③ Gunicorn の workers 数を適正化
🛠 次善策④ Gunicorn を gevent に変更
🛠 次善策⑤ Django のデータベースクエリを最適化
🔄 環境調整⑥ AWS Load Balancer のタイムアウトを延長
🔄 環境調整⑦ EC2 インスタンスのアップグレード

まずは Nginx・Gunicorn のタイムアウト設定を増やす ところから試し、ログを確認しながら対処していくと良いでしょう。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

コメント

コメントする


reCaptcha の認証期間が終了しました。ページを再読み込みしてください。

目次