HTTP 404・502・504はどの層で起きる? ― Nginxとアプリの通り道から切り分ける

ネットワーク・RFCカテゴリを表すパンダのイラスト ネットワーク・RFC

この記事について
この記事は、生成AIを活用した自動生成フローで作成しています。RFC 9110のHTTPステータス定義とnginx公式のproxy/FastCGIドキュメントを確認し、Web障害の最初の切り分けに使える形へ整理しています。

検証ステータス:🧪 RFC・nginx公式情報確認済み・localhostで404確認済み・502/504の故意の再現は未実施

HTTP 404・502・504はどの層で起きる? ― Nginxとアプリの通り道から切り分ける

404502504 はすべてHTTPステータスですが、意味は同じではありません。NginxをリバースプロキシやFastCGIの入口にしているなら、ステータス番号だけで原因を決めつけず、ブラウザ → Nginx → upstreamのどこまで処理が進んだかを確認します。

まずHTTP上の意味を分ける

StatusRFC上の意味を短く言うと最初に考えること
404 Not Foundorigin serverが対象リソースの現在の表現を見つけられない、または存在を明かしたくないURL・routing・静的ファイル・アプリ側route
502 Bad Gatewaygateway/proxyが上流から無効な応答を受け取ったupstream接続先・プロトコル・サービス・socket
504 Gateway Timeoutgateway/proxyが上流から必要な応答を時間内に得られなかったupstream遅延・timeout・詰まり

大切なのは、502 = PHPの文法エラー504 = Nginxが壊れた のように製品固有の原因へ直結させないことです。RFCが定義するのはHTTP応答の意味であり、実際の原因は構成によって変わります。

Nginxが間にいると通り道が増える

sequenceDiagram
    participant B as Browser
    participant N as Nginx
    participant U as Upstream / PHP-FPM
    B->>N: HTTP request
    alt Nginx自身で処理
        N-->>B: 2xx / 4xx など
    else upstreamへ転送
        N->>U: proxy_pass / fastcgi_pass
        U-->>N: response または失敗
        N-->>B: HTTP response
    end

同じ 404 でも、Nginxの静的ファイル探索で返った404と、upstreamアプリが返した404では調べる場所が違います。したがって、「誰がそのレスポンスを作ったか」を確認するのが第一歩です。

404ならURLだけを見ない

404では次を順に確認します。

  1. ブラウザが要求したpathは期待どおりか

  2. Nginxの location がどこへ振り分けているか

  3. 静的ファイルなら実ファイルとroot/aliasの関係は正しいか

  4. upstreamアプリなら、そのrouteが本当に存在するか

なおRFC 9110では、サーバーが対象リソースの存在を明かしたくない場合にも404を使えるため、404だけから「物理ファイルがない」とは断定できません。

502ならupstreamとの境界を見る

Nginxの proxy_passfastcgi_pass は、Nginxの先に別のサーバーやFastCGIプロセスがいる構成です。502が出たら、たとえば次を確認します。

  • upstreamのホスト・ポート・Unix socketは正しいか

  • upstreamプロセスは起動しているか

  • Nginxから接続できる権限・経路になっているか

  • HTTPで話す相手なのかFastCGIで話す相手なのか

  • error logにupstream接続時の具体的な失敗が残っていないか

「上流が落ちている」だけでなく、接続先の取り違えやsocket権限でも境界は壊れます。

504なら「遅い場所」を探す

504はgateway/proxyが上流応答を時間内に受け取れなかった状態です。単純にtimeout値を大きくする前に、upstream側で処理が止まっていないか、外部APIやDB待ちが長くないかを確認します。

timeoutの延長だけで症状が見えなくなると、根本原因の発見が遅れることがあります。

すぐ試す:localhostで404を本当に出してみる

説明だけでなく、まず404を自分のPCで観察してみます。Nginxの設定は変更せず、Pythonの簡易HTTPサーバーを 127.0.0.1 だけで起動します。

ターミナル1:

python3 -m http.server 8000 --bind 127.0.0.1

ターミナル2:

curl -i http://127.0.0.1:8000/not-found

not-found というファイルは作っていないので、簡易HTTPサーバーから 404 File not found が返ります。これで「404はHTTPレスポンスとして実際に返ってくる」というところを安全に確認できます。

実サイトの切り分けでは、本文を大量に表示せずstatus・header・接続先だけ見たいことがあります。GitHubサンプルでは次のように使えます。

./check-http-status.sh https://example.com/

表示するのは主にresponse header、HTTP status、remote IP、total timeです。URLは自分の確認対象へ置き換えます。

502や504を学ぶために本番Nginxのupstream設定を故意に壊す必要はありません。まずstatusを観察し、502ならupstreamとの接続境界、504ならupstreamの処理時間やtimeoutへ進む方が安全です。

最初の切り分け

flowchart TD
    A[HTTPエラーを確認] --> B{404?}
    B -- はい --> C[URL / location / route / fileを確認]
    B -- いいえ --> D{502?}
    D -- はい --> E[upstream接続・socket・protocol・logを確認]
    D -- いいえ --> F{504?}
    F -- はい --> G[upstream処理時間・timeout・依存先を確認]
    F -- いいえ --> H[別のstatus定義へ]

GitHubサンプル

公式情報・一次情報

ライセンス:本記事のテキスト/コードは特記なき限り CC BY 4.0 です。引用の際は出典URL(本ページ)を明記してください。
利用ポリシー もご参照ください。
タイトルとURLをコピーしました