胖叔网络科技 网络科技 · 技术笔记
置顶 部署运维

Nginx 502 与 504 排查手册:先分清是"连不上"还是"等太久"

502 和 504 看着都是网关错误,但成因完全相反:一个是上游根本没连上,一个是连上了但超时。搞混方向会让排查绕大圈。

# Nginx# 反向代理# 性能# 故障排查

#先建立正确的判断顺序

很多人在遇到 502 时第一反应是重启服务,这没错,但跳过了定位环节,下次还会犯。

正确的第一步是看错误日志里 Nginx 给出的原因:

Bash
tail -n 50 /www/wwwlogs/example.com.error.log

关键就两种:

日志关键字 含义 排查方向
connect() failed (111: Connection refused) 上游端口没人监听 进程挂了 / 端口错了
upstream timed out (110: Connection timed out) 连上了但响应太慢 业务卡住 / 超时设置太短

502 对应前者,504 对应后者。 这个区分能省掉一半的排查时间。

#情况一:502 —— 上游连不上

按这个顺序排查,每一步都能排除一类原因:

Bash
# 1. 进程活着吗
pm2 list

# 2. 端口在监听吗(这是最关键的一步)
ss -ltn | grep 3000

# 3. 从本机能不能打通
curl -I http://127.0.0.1:3000

# 4. 看应用自己的报错
pm2 logs nebula-blog --lines 50

如果第 2 步端口不存在,问题 100% 在应用侧,和 Nginx 无关。常见原因:

  • 应用启动就崩了:多半是环境变量缺失或依赖没装全
  • 监听地址写成了 0.0.0.0 以外的具体外网 IP:容器或某些环境下拿不到这个地址,导致绑定失败
  • 端口被别的进程占了ss -ltnp | grep 3000 能看到占用者

如果第 2 步端口在,但 curl 不通,检查 Nginx 配置里的 proxy_pass 地址是不是写错了端口。

一个容易被忽略的点:SELinux 开启时会拦截 Nginx 向本机端口的转发。用 getenforce 确认,如果是 Enforcing,需要 setsebool -P httpd_can_network_connect 1

#情况二:504 —— 等太久了

504 说明连接建立了,但上游在规定时间内没返回。Nginx 默认的 proxy_read_timeout60 秒

先判断是"偶发慢"还是"稳定慢":

  • 偶发:多半是某个接口在做重活(大批量导入、外部 API 调用)。解决办法是把这类请求异步化,而不是单纯调大超时。
  • 稳定慢:说明存在性能瓶颈,调超时只是掩盖问题。

如果确认是合理的长任务,再针对性放宽:

Nginx
location /api/export {
    proxy_pass http://127.0.0.1:3000;
    proxy_read_timeout 300s;      # 读取超时
    proxy_send_timeout 300s;      # 发送超时
    proxy_connect_timeout 15s;    # 连接超时,这个不要放大
}

注意 proxy_connect_timeout 不要跟着放大。 它的意义是"连不上就快速失败",调大只会让故障暴露得更晚。

#情况三:看起来是 502,其实是别的

有两种"假 502"值得单独提:

1. 响应头过大导致 502

上游返回的 Header 超过 Nginx 缓冲区大小时,Nginx 会报 upstream sent too big header。典型场景是应用写了很多 Cookie。

Nginx
proxy_buffer_size       16k;
proxy_buffers         4 32k;
proxy_busy_buffers_size 64k;

2. 请求体过大返回 413

上传大文件时报的不是 502 而是 413,需要在 Nginx 和 Node 两侧同时放开:

Nginx
client_max_body_size 120m;
JavaScript
app.use(express.json({ limit: '2mb' }));
// multer 的文件大小限制
multer({ limits: { fileSize: 100 * 1024 * 1024 } });

两侧限制必须一致或 Nginx 更宽,否则会出现"小文件能传、大文件报 502"这种诡异现象。

#一个通用的排查脚本

Bash
#!/usr/bin/env bash
# 用法:bash nginx-diag.sh example.com 3000
DOMAIN=${1:?域名}
PORT=${2:?端口}

echo "=== 1. Nginx 配置语法 ==="
nginx -t

echo "=== 2. 上游进程 ==="
pm2 list 2>/dev/null | head -10

echo "=== 3. 端口监听 ==="
ss -ltn | grep ":$PORT" || echo "!! 端口 $PORT 没有监听"

echo "=== 4. 本机直连 ==="
curl -s -o /dev/null -w "HTTP %{http_code} / 耗时 %{time_total}s\n" --max-time 10 "http://127.0.0.1:$PORT/healthz"

echo "=== 5. 最近错误日志 ==="
tail -n 20 "/www/wwwlogs/$DOMAIN.error.log" 2>/dev/null

echo "=== 6. SELinux ==="
getenforce 2>/dev/null || echo "未启用"

#相关资源

以下资料可直接下载:

SH

服务器只读巡检脚本

一条命令采集系统、CPU、内存、磁盘、Docker、端口与防火墙信息,不修改任何系统状态,适合部署前体检。

server-inspect.sh 1.4 KB 83 次下载

#小结

现象 本质 第一件事
502 连不上上游 ss -ltn 确认端口
504 上游响应超时 看业务日志找慢点
502 + too big header 响应头超缓冲区 proxy_buffer_size
413 请求体超限 同时改 Nginx 与应用限制

排查的本质是先把范围缩小到"应用侧"还是"网关侧",再往下钻。跳过这一步,就只能在黑暗中试错。

附件下载 共 1 个文件,点击直接下载

CONF

Nginx 反向代理站点配置模板

含 HTTPS 跳转、证书自动续期目录放行、WebSocket 升级、静态资源缓存与安全响应头的完整配置模板,改两个变量即可用。

nginx-site-template.conf 2.2 KB 87 次下载 来自:Nginx 502 与 504 排查手册:先分清是"连不上"还是"等太久"