
502・504エラーの切り分け|nginx・php-fpm・上流の順に見る
「サイトが見られない」と連絡が来て開いてみたら、画面には502 Bad Gateway。あるいは、しばらく待たされた末に504 Gateway Timeout——。 保守運用をしていると、この2つのエラーには何度も出くわしますよね。しかもたちが悪いのは、エラーを返しているnginxそのものは元気に動いていること。だから「どこを直せばいいのか」が一見わからず、あちこち再起動して回りたくなります。
でも、502も504も、実はnginxが「後ろにいる相手」とうまくやり取りできなかったというサインです。犯人はnginxの奥にいます。原因の場所さえ順番に絞れれば、やみくもに全部を再起動するより、ずっと早く・安全に落ち着けます。
この記事では、502・504が出たときに、nginxのエラーログを起点に、手前(Webサーバー)から奥(アプリ→上流)へ順番に切り分ける手順を一緒に整理します。構成(Apache+mod_php、nginx+php-fpm、ロードバランサー+アプリサーバーなど)で細部は変わりますが、「手前から奥へ」の考え方はそのまま使えます。
結論:まずエラーコードで大きく当たりをつけます。502は「後ろが応答を返せなかった/落ちている」、504は「後ろが時間内に返してこなかった=遅い」が基本の見分けです。そのうえで、①nginxのエラーログを見る(一次情報)→ ②アプリ(php-fpm等)の生死とログ → ③上流(DB・外部API)の遅延・詰まりの順に、手前から一段ずつ確かめます。いきなり再起動すると「たまたま直った」だけで原因が残り、また再発します。まずログで「どこで止まったか」を1つに絞るのが、結果的に一番早いです。
何が起きているか:nginxは「取次ぎ役」で、後ろが応えないと5xxを返す
502と504は、5xx=サーバー側のエラーの仲間です。ここで大事なのは、nginx(フロントのWebサーバー)は多くの場合、リクエストを受け取って後ろのアプリに取り次ぐ役だということです。後ろのアプリ(php-fpm、アプリケーションサーバー、別のnginx/Apacheなど)が正しく応えてくれて初めて、ページを返せます。
その「取次ぎ」がうまくいかないと、nginxは状況に応じて5xxを返します。ざっくり分けると次の通りです。
- 502 Bad Gateway:後ろにつなごうとしたのに、応答が壊れている・接続を拒否された・相手が落ちている。「後ろが応答を返せなかった」状態です。php-fpmが停止している、ソケットのパスがずれている、アプリが起動時にエラーで死んでいる、などが典型です。
- 504 Gateway Timeout:後ろにはつながったが、決められた時間内に返事が返ってこなかった。「後ろが遅い」状態です。重いSQL、外部APIの待ち、無限ループ気味の処理、アクセス集中でアプリの受け口が全部ふさがっている、などが典型です。
- どちらも「nginxが悪い」とは限らない:nginxは正直に「後ろがダメだった」と教えてくれているだけのことが多いです。だから、nginxだけを何度も再起動しても直らないことがよくあります。
つまり必要なのは、「後ろの誰が、どんなふうにダメだったか」を1つに絞る目です。次から、その順番を見ていきます。
手前から奥へ、3つの層で切り分ける

ポイントは、エラーを返しているnginxの一次情報から始めて、手前から奥へ進むことです。奥(DBなど)からいきなり触ると、原因でない層まで再起動して回ることになります。
① まず nginx のエラーログを読む(一次情報)
再起動よりも先にやるのは、nginxのエラーログを開くことです。502・504のときは、ここに「後ろとのやり取りで何が起きたか」がかなり具体的に残っています。
- エラーログの場所を確認する:多くの環境で
/var/log/nginx/error.logです(設定で変わるので、自分の現場のパスを把握しておきます)。 - 出た時刻あたりの行を見る:
tailやgrepで該当時刻を絞ります。502・504のときは、次のような手がかりが出ます。 connect() failed (111: Connection refused)… 後ろにつなげない。後ろが起動していない・ポートやソケットがずれているサイン(502寄り)。no live upstreams… 取り次ぐ先が全部ダウン扱い(502寄り)。upstream timed out (110: Connection timed out) while reading response header… つながったが時間内に返ってこない(504寄り)。- 502か504か、ログの言葉と一致するか確かめる:ブラウザで見えたコードと、ログの内容(refused系かtimeout系か)が合っているかを確認すると、次に疑う層が決まります。
ここで「connection refused(つなげない)」系なら、犯人は②アプリの生死の可能性が高いです。「timed out(遅い)」系なら、③上流の遅延を疑います。ログが指し示す方向へ進みます。
ここで一呼吸。ログを開くのは遠回りに感じるかもしれませんが、「どこで止まったか」を先に知るための一番の近道です。焦って再起動する前にログを見た、その判断がすでに落ち着いた一歩です。
② アプリ(php-fpm 等)の生死とログを見る
nginxのログが「つなげない(refused)」系だったり、502が続くなら、取り次ぐ先のアプリが動いているかを確かめます。
- プロセスが生きているか:php-fpmなら
systemctl status php-fpm(環境によりバージョン付きの名前)で稼働を確認します。落ちていれば、それが502の直接原因です。 - なぜ落ちた/つながらないのかを、アプリ側のログで見る:php-fpmのエラーログやアプリのログに、起動失敗・設定エラー・メモリ不足(OOM)などが残っていないかを見ます。「落ちたから再起動」だけで終えず、落ちた理由まで1行メモしておくと、再発時に効きます。
- つなぎ先(ソケット/ポート)のずれ:nginxの
fastcgi_passやproxy_passが指す先と、アプリが実際に待ち受けている場所が一致しているかを確認します。デプロイや設定変更の直後の502は、ここのすれ違いが定番です。 - 受け口が全部ふさがっていないか:php-fpmの同時処理数(
pm.max_children等)を超えるアクセスが来ると、新しいリクエストが待たされ、502や504につながります。この場合は「落ちている」のではなく「手が足りていない」状態です。
再起動して直ったとしても、②で見た「落ちた理由・詰まった理由」を残すこと。理由が分からないままだと、同じ時間帯にまた再発します。
③ 上流(DB・外部API)の遅延・詰まりを見る
504が中心だったり、アプリは生きているのにレスポンスが返ってこないなら、アプリのさらに奥を疑います。アプリは「上流の返事待ち」で固まっていることが多いです。
- 重いSQL・DBの詰まり:スロークエリ、ロック待ち、コネクション枯渇などで、アプリがDBの返事を待ち続けていないか。DB側のプロセス一覧やスローログを確認します。
- 外部APIやバッチの巻き込み:決済・在庫連携などの外部APIが遅い/落ちていると、それを待つページだけが504になります。「特定ページだけ遅い」なら、その処理が呼ぶ相手を疑います。
- タイムアウト設定と実態のズレ:nginx側の
proxy_read_timeout/fastcgi_read_timeoutを超えると504になります。まずなぜ遅いのか(上流)を直すのが本筋で、タイムアウト値を延ばすのは応急処置です。安易に延ばすと、遅い処理が居座って受け口を長くふさぎ、かえって全体が詰まることもあります。
この層は影響範囲が大きいので、設定値やSQLを触る前に、いまの値と状態をメモしてから動きます。「元に戻せる状態」を保ったまま、一段ずつ確かめます。
具体例:「昼の時間帯だけ504が出る」を追う
よくある報告で、順番に切り分けてみます。
- ①nginxのログ:504が出た時刻に
upstream timed out ... while reading response headerが並んでいた。「つながっているのに遅い」と判明。犯人は奥(②か③)。 - ②アプリ:php-fpmは生きている。ただしアクセスが増える昼の時間帯に、処理中のワーカーが上限近くまで埋まっていた。「落ちている」のではなく「詰まっている」。
- ③上流:詰まりの元をたどると、ある一覧ページの検索が重いSQLを投げ、DBのロック待ちが伸びていた。そのページの表示が長引き、ワーカーを占有し、他のページまで504に巻き込んでいた。
- 対処:まずは重いSQLに絞って原因を切り分け(インデックスの見直し・取得件数の制限など)。タイムアウト値を延ばすのは、その場しのぎとしてだけ使い、根本は上流の遅さの解消に置いた。
もし最初に「とりあえずnginxとphp-fpmを再起動」をしていたら、一時的にワーカーが空いて直ったように見えても、昼になればまた同じ504が出ていたはずです。ログから「遅い(504)→ 上流が重い」とたどれたからこそ、次に活きる原因にたどり着けました。
影響:切り分けの順番を持つと、何が変わるか
502・504の切り分け順を1枚持っておくと、直す力そのものより先に、焦りと手戻りが減ります。
- 「nginxが悪いのかも」と思い込む前に、「後ろの誰かが応えられなかっただけかも」と一度立ち止まれる。
- 502(落ちている)か504(遅い)かで、最初に見る場所を分けられる。
- 関係ない層まで再起動して回らずに済み、「たまたま直った」を「原因が分かって直った」に変えられる。
- タイムアウト値を延ばすだけの対症療法に逃げず、上流の遅さという本丸に向かえる。
逆に、毎回いきなり全部を再起動していると、直った日と、原因が残って半日溶かす日の差が大きくなります。順番は、その日の自分を助ける道具です。
明日やること:自分の現場の「取次ぎ地図」を1枚書く
立派な資料は要りません。明日できる、いちばん小さな一歩はこれです。
- 自分が担当するサイトで、リクエストがユーザー→どこ→どこと流れるかを書き出す(例:nginx → php-fpm → MySQL、途中に外部API)。
- それぞれの層について、「ログの場所」と「生死の確認コマンド」を1行メモする(nginxのerror.log、php-fpmのstatus確認、DBのプロセス確認など)。
proxy_read_timeout/fastcgi_read_timeoutなどのいまのタイムアウト値を控えておく。504のとき「実態と合っているか」をすぐ照らせます。- 次に502/504が出たら、この地図を手前(nginxログ)から順にたどる。
- 実際に効いた層と原因を書き足し、「この時間帯はここが詰まりやすい」を言語化する。
きれいに描かなくて大丈夫です。「どこを経由して、どこで止まりうるか」の地図が1枚あるだけで、次の自分(や引き継ぐ人)が、やみくも再起動のループに迷い込まずに済みます。
502・504切り分けチェックリスト
切り分けに着手するとき、これだけ確認できているかを見る項目です。コピーして、自分のメモに当ててみてください。全部を毎回そろえる必要はありません。
まず外せない最低ラインはこの3つです。急いでいても、ここだけは押さえます。
- 【最低ライン】再起動する前に、まずnginxのエラーログ(該当時刻)を開いたか
- 【最低ライン】502(つなげない/落ちている)か504(遅い)かで、疑う層を分けたか
- 【最低ライン】nginx→アプリ→上流の順に、手前から一段ずつ確かめたか
次の項目は、手前で片づかないとき・原因が奥にありそうなときに追加で確認します。当てはまらなければ飛ばして大丈夫です。
- エラーログの文言(refused系かtimeout系か)と、見えたコードが一致しているか見たか
- アプリ(php-fpm等)の生死と、落ちた/詰まった理由をログで確かめたか
- nginxのつなぎ先(ソケット・ポート)とアプリの待ち受けがずれていないか見たか
- 504なら、上流(重いSQL・ロック待ち・外部APIの遅延)を疑ったか
- タイムアウト値を延ばすのは応急処置と割り切り、上流の遅さの解消を本筋に置いたか
- 設定値やSQLを触る前に、いまの値・状態をメモして戻せるようにしたか
- 効いた層と原因をメモに残し、再発時に活かせるようにしたか
全部に○が付かなくても大丈夫です。最低ラインの3つ、とくに「再起動の前にnginxのログを開いたか」さえ押さえられれば、やみくもに再起動して消耗するより、ずっと確かな一歩になります。
よければ、こちらも
502・504の切り分けは、落ち着いて動くための「順番」と「見る場所」があるほど楽になります。ログの見方と、遅さ・詰まりの調べ方をセットにしておくと、次の5xxがだいぶ軽くなります。
- 500エラーが出たら最初に見る5つのログ|場所と確認の順番:5xxが出たとき、どのログをどの順で見るかをまとめています。502・504の一次調査の土台になります。
- 大量ログからエラーを絞り込む|grep・tail・lessの実務術:nginxやアプリのログから該当時刻を素早く絞る、日々の手を軽くする調べ方です。
- DBコネクション枯渇・デッドロックの見つけ方と一次対処:504の奥でよくある「上流のDBが詰まる」パターンを、見つけ方から一次対処まで整理しています。

502・504がこわいのは、エラーを返しているnginxは元気なのに、原因がどこにいるのか見えないからです。でも、「後ろの誰かが応えられなかっただけ」と考えて、ログを手前から順にたどると決めるだけで、霧はかなり晴れます。多くの場合、あなたの設定が全部おかしいわけではなく、ただ後ろのどこか一段で止まっていただけです。 今日は、自分の現場の「取次ぎ地図」を1枚描いてみるところからで十分です。その1枚が、次の5xxを、迷路ではなく手順に変えてくれます。
ほかの実務ヒントは記事一覧からどうぞ。保守運用の小さな備えを、メールでも少しずつお届けしています。