Skip to main content

502 Bad Gateway 怎么排查?从 Nginx 日志找到真正出错的上游

October 17, 2026
从一条失败请求和 Nginx 上游日志出发,排查 502 Bad Gateway 的连接、协议、权限、响应头与应用资源问题,区分 HTTP 与 FastCGI,并给出验证和配置回退方法。
502 Bad Gateway 怎么排查?从 Nginx 日志找到真正出错的上游

更新日期:2026-10-18

遇到 502,先不要同时重启 Nginx、应用和数据库。502 表示网关收到无效的上游响应一类问题,但仅凭浏览器里的状态码,无法知道是哪一层网关、哪个上游出了问题。

本文面向 Linux 上的 Nginx HTTP 反向代理。请求可能经过 CDN、Nginx,再到应用;PHP-FPM 使用 FastCGI,诊断思路相似但协议和配置指令不同。应用返回的 502、自定义错误页和代理重试,也可能影响最终看到的结果。

先保存一条失败请求

记录时间、URL、方法、状态码和请求标识。避免把 Cookie、Authorization 或完整业务请求体贴到公开工单。

如果问题刚发生,先查看 Nginx 服务状态与最近日志:

sudo systemctl status nginx --no-pager
sudo journalctl -u nginx --since '10 minutes ago' --no-pager
sudo tail -n 80 /var/log/nginx/error.log

日志路径以实际配置为准。systemd 日志不一定包含全部请求错误,容器部署可能把日志输出到标准输出。先确认日志去了哪里,再谈“日志没有错误”。

让访问日志包含上游信息

下面的配置放在 http 上下文。先备份当前配置,确认日志目录存在,再加入格式和对应访问日志:

log_format mf8_upstream '$time_iso8601 $request_id $request_method $uri '
                        'status=$status upstream=$upstream_addr '
                        'upstream_status=$upstream_status '
                        'request_time=$request_time '
                        'connect=$upstream_connect_time '
                        'header=$upstream_header_time '
                        'response=$upstream_response_time';
access_log /var/log/nginx/upstream.log mf8_upstream;

示例省略查询串,减少令牌或业务参数进入日志的机会;路径本身也可能含敏感信息,需要结合应用设计处理。多个上游尝试可能产生多值字段,应整体阅读,不能只取最后一段。

验证成功再重载:

sudo nginx -t
sudo systemctl reload nginx

若校验失败,不重载,按错误位置修复。若重载后行为异常,恢复备份配置,再次通过 nginx -t 后重载。

根据错误信息分支排查

日志特征常见检查方向不宜直接采取的动作
connection refused进程、地址、端口、启动状态一味增大超时
no live upstreams上游状态、失败判定、解析与配置只重启浏览器
upstream prematurely closed connection应用崩溃、连接被关闭、协议不匹配假定一定是 Nginx 缓冲区小
upstream sent too big header响应头和 Cookie 规模无上限地加大所有缓冲区
SSL handshake failed上游 TLS、SNI、证书、协议永久关闭证书校验
Permission deniedUnix socket、目录权限、安全策略全目录 chmod 777

超时通常还可能对应 504。若上层重试或自定义处理改变了状态码,应追查实际错误日志,而不是只根据 502/504 标签分类。

从 Nginx 所在位置访问上游

假设配置中的 HTTP 上游是 127.0.0.1:8000,在相同网络环境中执行:

ss -lntp
curl -v --max-time 10 http://127.0.0.1:8000/

如果连接拒绝,先看应用是否监听这个地址。应用只监听 IPv6、本机另一端口或容器内地址,都会使“进程存在”和“上游可达”出现差距。

如果 Nginx 在容器里,容器中的回环地址不是宿主机。应进入它实际使用的网络环境测试,并确认服务名解析和网络连接。宿主机 curl 成功不能替代容器内部的连通性检查。

按 Host 分站的应用,还需要携带预期 Host 测试。HTTPS 上游则应保留正确主机名与证书验证,不能只用 IP 加 -k 得到一次成功就认为配置无误。

PHP-FPM 的 socket 不是 HTTP 服务

若配置使用 fastcgi_pass,不要把 PHP-FPM 端口当 HTTP 服务用 curl 验证。应检查 FPM 进程、pool 配置、监听 socket、权限和日志,再通过 Nginx 的 PHP 请求验证完整链路。

Unix socket 的文件权限和父目录可遍历权限都可能影响访问;SELinux 或 AppArmor 等机制也可能拒绝连接。应根据拒绝日志修改最小必要配置,不要直接关闭整套安全机制。

还要确认 Nginx 与 FPM 对脚本路径的理解一致。迁移目录、容器挂载或修改 document root 后,旧路径可能继续留在 FastCGI 参数里。

区分应用故障与资源瓶颈

如果上游偶发退出,检查同一时间的应用异常、进程退出码、OOM 与重启记录:

sudo journalctl -k --since '20 minutes ago' --no-pager
free -h
df -h
df -i

磁盘满、inode 耗尽、数据库连接池耗尽和工作进程崩溃,都可能在网关层表现为失败。不要看到 Nginx 错误就只修改 Nginx。

对于“响应头过大”,先看应用是否异常生成大量 Cookie 或重定向状态,再按实际响应规模评估 proxy_buffer_size;FastCGI 使用对应的 FastCGI 指令。两套参数不能混用。

恢复之后,如何确认修好了

不要只刷新首页。使用原来的失败请求复测,再检查相同时间段的上游日志、业务动作与错误率。若问题只在并发时出现,要在受控环境复现负载,而不是向生产随意加压。

至少保留:故障时间、受影响链路、根因证据、修改项、回退方式和复测结果。如果只是重启后暂时恢复,应明确根因尚未确认,继续观察应用与资源指标。

如果入口是 Cloudflare Tunnel,可结合Tunnel 排障判断连接器和源站之间的故障;如果是 AI 流式接口,还要检查流式代理与超时。

官方资料与继续阅读