504 Gateway Time-outの修正:Nginxアップストリームタイムアウトの解決方法

intermediate🌐 Networking2026-06-15| Linux (Ubuntu/CentOS/Debian), Nginx 1.18+, PHP-FPM, Python/Gunicorn, Node.js

Error Message

504 Gateway Time-out
#nginx#ゲートウェイタイムアウト#ネットワーク#プロキシ#php-fpm#devops

問題点

ブラウザに 504 Gateway Time-out エラーが表示され、真っ白な画面を眺めることほどストレスが溜まることはありません。これは、Nginxが仲介役(プロキシ)として動作し、PHP-FPM、Gunicorn、Node.jsなどのバックエンドへリクエストを正常に転送したものの、バックエンドからの応答に時間がかかりすぎている場合に発生します。技術的には、許可された時間内にレスポンスが届かなかったため、Nginxがしびれを切らして接続を遮断した状態です。

根本原因の特定

設定ファイルをむやみに調整し始める前に、Nginxのエラーログを確認して、どのサービスが停滞しているかを特定しましょう。次のコマンドを実行すると、ログをリアルタイムで監視できます。

sudo tail -f /var/log/nginx/error.log

次のような行がないか探してみてください。

[error] 12345#0: *678 upstream timed out (110: Connection timed out) while reading response header from upstream, client: 1.2.3.4, server: example.com, request: "GET /api/reports HTTP/1.1", upstream: "http://127.0.0.1:8000/api/reports"

もし "upstream timed out" と表示されている場合は、ポート 8000 で動作しているアプリケーションがボトルネックであることを裏付けています。デフォルトでは、Nginxはレスポンスを60秒間待ちます。レポートの生成やAPI呼び出しに61秒かかると、504エラーがトリガーされます。

解決策1:Nginxプロキシのタイムアウト値を増やす

NginxをNode.js、Python、Goのリバースプロキシとして使用している場合、サーバーブロックまたはロケーションブロックの待機時間を延長する必要があります。重い処理には300秒(5分)あれば十分であることが多いです。

サイトの設定ファイル(通常は /etc/nginx/sites-available/default)を開き、以下の行を更新します。

location / {
    proxy_pass http://your_backend;
    proxy_connect_timeout 300s;
    proxy_send_timeout 300s;
    proxy_read_timeout 300s;
    send_timeout 300s;
}
- **proxy_connect_timeout:** Nginxがバックエンドとのハンドシェイクを確立するまでの待機時間。
- **proxy_read_timeout:** 最も一般的な原因です。接続が確立された後、Nginxがバックエンドからのデータ送信を待つ時間。
- **proxy_send_timeout:** Nginxがバックエンドへのリクエスト送信を完了するまでの待機時間。

解決策2:PHP-FPMの504エラーを修正する

WordPressやLaravelのサイトでは、Nginxの設定変更だけでは不十分です。PHP-FPMには独自の内部タイマーがあり、Nginxが待機していてもスクリプトを強制終了してしまいます。

1. NginxのFastCGI設定を更新する

location ~ \.php$ {
    include snippets/fastcgi-php.conf;
    fastcgi_pass unix:/var/run/php/php8.2-fpm.sock;
    fastcgi_read_timeout 300s;
}

2. PHP-FPMのプール設定を更新する

プール設定(例:/etc/php/8.2/fpm/pool.d/www.conf)を編集し、request_terminate_timeout をNginxの設定と一致させます。

request_terminate_timeout = 300

3. php.iniを更新する

最後に、PHPの実行制限時間が延長した時間を許容できるように設定します。

max_execution_time = 300

解決策3:Python(Gunicorn/Uvicorn)の504エラーを修正する

Gunicornはデフォルトのタイムアウトがわずか30秒と非常に厳格です。データの書き出しに35秒かかると、Gunicornはワーカープロセスを強制終了します。その結果、接続が消失したためにNginxが504エラーを報告することになります。

タイムアウトフラグを高く設定してGunicornを起動します。

gunicorn --timeout 300 myapp.wsgi:application

検証手順

設定を調整したら、Nginxの構文が有効であることを確認します。

sudo nginx -t

テストに合格したら、サービスをリロードして新しい制限を適用します。

sudo systemctl reload nginx
sudo systemctl restart php8.2-fpm  # PHPを使用している場合のみ

リクエストを再度テストしてください。ちょうど300秒後にまだ504エラーが発生する場合は、CloudflareやAWSロードバランサーなど、さらに上位(アップストリーム)でタイムアウトが発生している可能性があります。

予防と最適化

タイムアウト値を上げればエラーページは表示されなくなりますが、バックエンドの低速化が解決するわけではありません。実行時間の長いリクエストはワーカープロセスを占有し、トラフィックが多いときには最終的にサーバーをダウンさせる可能性があります。

- **データベースクエリの最適化:** 50万行あるテーブルのインデックスが不足していることは、504エラーの典型的な原因です。
- **バックグラウンドジョブへのオフロード:** 50通のメール送信やPDFの生成など、タスクに10秒以上かかる場合は、ユーザーを待たせてはいけません。CeleryやRedisなどのキューを使用し、すぐに「処理中」というメッセージを返却するようにしましょう。
- **ネットワークの調査:** Nginxとバックエンドが別のサーバーにある場合、遅延がタイムアウトまでの時間を削ってしまうことがあります。VPCを設計する際、内部ルーティングが効率的で不要なホップが発生していないか確認するために、私はよくこの [サブネット計算機](https://toolcraft.app/en/tools/developer/ip-subnet-calculator) を使用します。

まとめ

504 Gateway Time-outは、本質的に「バックエンドが苦労している」というNginxからのメッセージです。恒久的に修正するには、ブラウザ、ロードバランサー、Nginx、そして最後にアプリケーションサーバー自体まで、スタック全体のタイムアウト値を調整する必要があります。このチェーンのどこか1箇所でもタイムアウトが早すぎると、リクエスト全体が失敗してしまいます。

Related Error Notes