504 Gateway Timeout:意味と対処法
· 読了目安 2 分
エラーの意味
504 は、手前のウェブサーバー(nginx、Apache、ロードバランサー、CDN)が、背後のアプリケーションを待つのを諦めた状態です。リクエストは渡され、バックエンドは作業を始めましたが、応答が返る前に、手前のタイマーが切れました。502 Bad Gateway との違いは、バックエンドには到達できることです。ただ、遅すぎるのです。一般的なタイマーは、nginx で 60 秒(fastcgi_read_timeout、proxy_read_timeout)、Apache で 60 秒(ProxyTimeout)、Cloudflare で 100 秒(無料プランでは変更できません)です。
タイムアウトを引き上げることが解決策になることは、めったにありません。何かに時間がかかりすぎていて、その何かを見つける必要があります。
よくある原因
- 遅いデータベースクエリです。 ページを読み込むたびに巨大なテーブルの行数を数える WordPress のプラグイン、足りないインデックス、期限切れのトランジェントでいっぱいの
wp_optionsテーブル。すべてのリクエストが待たされ、負荷がかかると、その待ち時間が積み重なります。 - 外部への呼び出しがハングしています。 アプリケーションが、決済プロバイダー、メールサービス、天気 API、ライセンスサーバーに接続し、そのサービスが遅いか、ダウンしています。その呼び出しにタイムアウトがないと、ページはそれを待ち続けます。
- ワーカーが少なすぎます。 PHP-FPM のワーカーがすべて、遅いリクエストで使用中で、新しいリクエストは、手前が諦めるまで待たされます。外から見ると、個々のリクエストは速いはずなのに、タイムアウトのように見えます。
- cron やバックアップがフォアグラウンドで動いています。 バックアップのプラグイン、インポート、5 万 URL のサイトマップ。ウェブリクエストの中で生成されると、どんなタイムアウトも超えてしまいます。
- ディスク I/O またはスワップです。 サーバーがメモリ不足になってスワップし、すべてが 10 倍遅くなります。CPU 使用率は低いのに、負荷が高い状態として見えます。
- 手前と背後の間のネットワークです。 ロードバランサーが 1 つのデータセンター、バックエンドが別のデータセンターにあり、ファイアウォールがパケットを黙って破棄しています。まれですが、バックエンドが空いているのに、すべてのリクエストで 504 が出る場合は、ここが疑われます。
訪問者の場合
1 分後に再読み込みしてください。サイトがダウンではなく遅い場合は、別のページを試してください。タイムアウトが、1 つの重いページに結び付いている可能性があります。
ご自身のサイトの場合:まず確認
ウェブサイトダウンチェッカーを実行してください。外部からのステータスコードと応答時間が表示されます。今日 30 秒で応答するサイトは、明日、負荷がかかると 504 を出すサイトです。
ご自身のサーバーでは、時間がかかっている場所を探します。
# ワーカーが溜まっていないか?
sudo tail -n 30 /var/log/nginx/error.log | grep -E 'timed out|timeout'
# PHP は今何をしているか?(プールの pm.status_path が必要)
curl -s 'http://127.0.0.1/fpm-status?full' | grep -E 'state|request URI|duration' | head -40
# MySQL/MariaDB:どのクエリが、どれくらいの時間、実行されているか?
sudo mysql -e 'SHOW FULL PROCESSLIST;'
# メモリとスワップ
free -m
vmstat 1 5
同じクエリで埋め尽くされたプロセス一覧、またはゼロではない vmstat の si/so 列が、原因を示しています。
ご自身のサーバーでの対処法
1. スロークエリログを有効にして、クエリを修正する
SET GLOBAL slow_query_log = 1;
SET GLOBAL long_query_time = 2;
SET GLOBAL slow_query_log_file = '/var/log/mysql/slow.log';
数分後、sudo mysqldumpslow -s t /var/log/mysql/slow.log | head で、最悪のクエリが一覧表示されます。足りないインデックスを追加するか、そのクエリを実行しているプラグインを見つけて置き換えてください。WordPress では、肥大化した options テーブルが典型例です。
wp transient delete --all
wp db query "SELECT option_name, LENGTH(option_value) AS size FROM wp_options WHERE autoload='yes' ORDER BY size DESC LIMIT 20;"
リクエストのたびに自動読み込みされる、数百キロバイト規模のものは、削除の候補です。
2. 外部への呼び出しにタイムアウトを設定する
アプリケーションが行うすべての HTTP 呼び出しには、ウェブサーバーのものより短い、独自のタイムアウトが必要です。cURL を使う PHP では:CURLOPT_CONNECTTIMEOUT を 5、CURLOPT_TIMEOUT を 10 に。WordPress では、wp_remote_get() に timeout 引数があります。多くのプラグインはこれを初期値のままにして、いつまでも待ち続けます。サードパーティのサービスがダウンしている場合は、ページが落ちるのではなく、機能を縮退させる(リアルタイムの送料なしでフォームを表示する)べきです。
3. 長い処理をリクエストの外に出す
バックアップ、インポート、エクスポート、大きなサイトマップ、メール送信は、ページの表示ではなく、cron ジョブやキューで行うべきです。WordPress では、疑似 cron を無効にして、本物の cron を実行します。
// wp-config.php
define('DISABLE_WP_CRON', true);
# crontab -e
*/5 * * * * cd /var/www/example.com && wp cron event run --due-now >/dev/null 2>&1
4. タイムアウトを調整する(慎重に)
1 つのページが正当により長い時間を必要とする場合(管理画面のエクスポートやレポートなど)は、全体ではなく、その location だけタイムアウトを引き上げます。
location = /wp-admin/export.php {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php8.3-fpm.sock;
fastcgi_read_timeout 300;
}
Apache と PHP-FPM の場合:<Location> ブロックの中で ProxyTimeout 300。PHP 自体にも max_execution_time があります。同じ値に設定してください。そうしないと、PHP が先に止まり、504 ではなく 500 が出ます。そのうえで、sudo nginx -t && sudo systemctl reload nginx。
5. スワップを止める
ps aux --sort=-%mem | head
PHP-FPM のワーカーが 1 つあたり 150 MB を使い、4 GB のサーバーで 30 個動かしているなら、計算が合いません。pm.max_children を下げる、メモリを増やす、またはメモリを使っているプラグインを修正してください。スワップしないサーバーは、504 の大半がなくなるサーバーです。
6. キャッシュ
フルページキャッシュ(nginx の FastCGI キャッシュ、WordPress のキャッシュプラグイン、Varnish)は、PHP やデータベースに触れずに、リピート訪問者へ配信します。負荷時の 504 の大半は、トップページと主要なページがキャッシュから配信されるようになると、なくなります。
ホスティング会社の問題の場合
共有ホスティングでは、遅いクエリとプラグインは修正できますが、サーバーのタイムアウトや、同じサーバーを使う他のアカウントの負荷は修正できません。ホスティング会社に次の文面を送ってください。
お世話になっております。ウェブサイト example.com が、16:00 UTC 頃から「504 Gateway Timeout」を返しています。以前は 2 秒未満で読み込めていたページがタイムアウトします。こちらでは何も変更していません。データベースサーバーまたは私のアカウントの PHP プールが過負荷になっていないか、あるいはサーバー上の別のアカウントが高い負荷の原因になっていないかを確認し、わかったことを教えていただけますでしょうか。
次回に備えて
504 は、遅いサイトがさらに遅くなった状態であり、応答時間は、タイムアウトのずっと前から計測できます。ウェブサイトのチェックは、チェックごとに応答時間を記録します。それにアラートを設定すれば、訪問者がエラーを見る数週間前に、その傾向がわかります。サーバーエージェントは、内部からの負荷、メモリ、スワップを加えます。ご自身のサーバーでは、Deep Fix が遅いクエリやハングしている呼び出しを見つけて修復します。15 分単位で請求され、料金は依頼の前に表示されます。
次のステップ
ダウンしても、すぐ対応します。
ご自身のサーバー、または SSH アクセスのあるウェブスペースが対象です。一般的な原因には定額の Quick Fix、それ以外には 15 分単位で請求する Deep Fix を、24 時間体制でご用意しています。ご依頼の前に料金が表示されます。
修復を依頼する