エラーメッセージ
Nginxのエラーログ(通常は /var/log/nginx/error.log にあります)を確認すると、以下のような特定の行に遭遇することがあります。
[error] 1234#0: *5678 upstream prematurely closed connection while reading response header from upstream, client: 1.2.3.4, server: example.com, request: "POST /api/data HTTP/1.1", upstream: "http://127.0.0.1:8080/api/data"
主な原因
このエラーは、Nginxがバックエンド(アップストリーム)への接続とリクエストの送信に成功したものの、バックエンドがHTTPレスポンスヘッダーの送信を完了する前にTCP接続を終了したことを示しています。これは通常、以下の4つの理由で発生します。
- バックエンドのクラッシュ: リクエストの処理中に、アプリケーションプロセス(Node.js, Python, PHPなど)がクラッシュしたか、OOM(メモリ不足)により強制終了された。
- タイムアウトの不整合: バックエンド側のタイムアウト設定がNginxよりも短く、処理の途中で接続が切断された。
- バッファオーバーフロー: バックエンドから送信されたレスポンスヘッダーが、Nginxの現在のバッファ設定に対して大きすぎる。
- Keep-aliveの問題: Nginxがまだ有効であると認識していた持続的接続を、バックエンド側が閉じてしまった。
ステップ別の修正方法
1. バックエンドアプリケーションの状態を確認する
最も一般的な原因は、リクエストの途中でバックエンドサービスが失敗することです。すぐにアプリケーションログを確認してください。例えば、systemdを使用している場合は以下の通りです。
# サービスの状態と最近のログを確認
journalctl -u my-backend-service -n 50 --no-pager
セグメンテーション違反(Segmentation Fault)、メモリ不足(OOM)エラー、または未処理の例外を探します。バックエンドがクラッシュしている場合は、Nginxの設定をいじる前に、コードを修正するかサーバーのRAMを増設してください。
2. プロキシバッファサイズを増やす
アプリケーションが大きなCookieや多くのカスタムヘッダーを送信する場合、ヘッダーがバッファサイズを超えるとNginxが接続を切断することがあります。location または http ブロックに以下のディレクティブを追加してください。
location / {
proxy_buffer_size 128k;
proxy_buffers 4 256k;
proxy_busy_buffers_size 256k;
proxy_pass http://your_backend;
}
保存後、Nginxのテストとリロードを行います。
nginx -t && systemctl reload nginx
3. Keep-Alive設定を同期させる
バックエンドがすでにタイムアウトして閉じた接続をNginxが再利用しようとすると、このエラーが発生します。Nginxとバックエンドの間で、接続を維持する時間(Keep-alive)の認識を一致させてください。proxy_keepalive を無効にするか、バックエンドのタイムアウトをNginxよりも長く設定します。
upstream ブロックの設定例:
upstream my_backend {
server 127.0.0.1:8080;
keepalive 32;
keepalive_requests 100;
keepalive_timeout 60s;
}
エラーが解消されない場合は、proxy_http_version 1.1; と proxy_set_header Connection ""; を設定して、Keep-aliveを適切に処理するように試みてください。
4. バックエンドの実行タイムアウトを増やす
バックエンドの応答に時間がかかりすぎると、バックエンド内部のタイムアウト(PHPの max_execution_time や Gunicornの timeout など)に達してソケットが閉じられることがあります。これらの値をNginxの proxy_read_timeout に合わせて増やしてください。
Nginxの設定例:
location /api/ {
proxy_read_timeout 300s;
proxy_connect_timeout 300s;
proxy_send_timeout 300s;
proxy_pass http://your_backend;
}
動作確認
修正を確認するには、失敗していた特定のエンドポイントに対して curl で負荷をかけます。
curl -I -X POST https://example.com/api/data
リクエストを実行しながら、リアルタイムでエラーログを監視します。
tail -f /var/log/nginx/error.log
HTTP 502/504エラーが消え、新しい「prematurely closed」のログが表示されなくなれば、設定は安定しています。
予防策
- モニタリング: 5xxステータスコードやバックエンドプロセスの再起動に関するアラートを設定する。
- リソース制限: バックエンドが同時接続を処理するのに十分なファイル記述子(
ulimit -n)を持っていることを確認する。 - 正常なシャットダウン(Graceful Shutdown): デプロイ中にアクティブな接続が切断されないよう、アプリケーションがSIGTERMを適切に処理できるようにする。

