更新日期: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 denied | Unix 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 流式接口,还要检查流式代理与超时。

