Nginx 反向代理 502/504 排查:先分清是谁超时,再按这四步定位
线上服务突然返回 502 Bad Gateway 或 504 Gateway Timeout,第一反应往往是“重启 Nginx”。但 502 和 504 背后的原因完全不同:502 是上游没有给出合法响应,504 是上游响应太慢。先分清是哪一种,再动手,能少走很多弯路。本文按一次真实的线上排查顺序,把方法固定成四步。
一、第一步:先看日志定性,不要先改配置
Nginx 的 error_log 是第一现场。先看最近一分钟的报错,再看 access_log 里的上游状态码和耗时:
tail -n 200 /var/log/nginx/error.log
awk '{print $9, $NF}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | head
常见的三类定性信号要分清:
upstream prematurely closed connection:上游在返回完整响应前断开了连接,多半是上游进程崩溃、被 OOM 杀掉,或者后端主动关闭了连接。no live upstreams:上游全部被标记为不可用,Nginx 已经没有可用的后端可以转发。upstream timed out:Nginx 在等待上游时超时,这通常对应 504,而不是 502。
同时在 access_log 里记录 $upstream_status 和 $upstream_response_time,如果状态码是 502 但上游耗时很短,问题多半在连接阶段;如果耗时恰好卡在 proxy_read_timeout 的数值附近,问题多半在上游处理太慢。
二、第二步:502 先绕过 Nginx,直接测上游
502 的核心问题是“上游没给合法响应”。最直接的办法是绕过 Nginx,直接请求后端:
curl -v http://127.0.0.1:8080/health
ss -tlnp | grep 8080
ps aux | grep -E 'java|gunicorn|php-fpm' | grep -v grep
按这个顺序排查:
- 端口是否在监听:后端进程没起来、监听地址写成了 127.0.0.1 但 Nginx 配的是内网 IP、端口号写错,都会直接 502。先核对 nginx.conf 里的 upstream 地址和后端实际监听地址是否一致。
- 进程是否还活着:用
systemctl status看后端服务状态,再看 dmesg 或系统日志有没有 OOM Killer 的记录。服务刚部署完就 502,优先查启动日志,而不是反复重启 Nginx。 - 协议是否对得上:Nginx 用 http 协议转发,后端却只监听了 https,或者后端要求 SNI、要求特定的 Host 头,也会返回非法响应。可以用 curl 加上
-H "Host: xxx"逐项复现。 - 权限与连接数:Unix Socket 方式转发时,Socket 文件权限不对、后端连接池打满,同样会表现为 502。检查 Socket 文件的属主和权限,以及后端的连接数上限。
如果绕过 Nginx 直接访问后端也是失败的,问题就在后端本身,不要再调 Nginx 的超时参数。
三、第三步:504 先分清是谁慢,再决定调哪个超时
504 的核心问题是“上游太慢”。Nginx 有三个超时要分清:
proxy_connect_timeout:和上游建立连接的超时,默认 60 秒,一般不用动。proxy_send_timeout:向发送请求体的超时。proxy_read_timeout:等待上游响应的超时,这是 504 最常见的触发点。
排查顺序建议这样:
- 看
$upstream_response_time:如果每次都恰好等于 proxy_read_timeout,说明后端确实在规定时间内没有返回。 - 在后端侧看慢日志:数据库慢查询、外部接口调用耗时、文件上传后的同步处理,都是常见拖慢点。先看后端的耗时分布,再决定是优化代码还是调整超时。
- 只在确认后端偶发变慢、且业务允许等待时,才适度调大 proxy_read_timeout,例如从 60 秒调到 120 秒,并且同步检查后端和数据库的连接池是否够用。
location /api/ {
proxy_pass http://backend;
proxy_connect_timeout 5s;
proxy_send_timeout 60s;
proxy_read_timeout 120s;
}
注意不要把超时无限制调大:超时调得越大,慢请求占用的连接就越多,一旦后端真的卡死,Nginx 的 worker_connections 很快会被占满,整个站点都会跟着不可用。调超时之前,先确认后端有熔断或限流兜底。
四、第四步:查资源与健康检查,避免反复复发
前三步解决的是单次故障,第四步解决的是反复复发:
- 上游健康检查:用
max_fails和fail_timeout把连续失败的上游暂时摘掉,避免 Nginx 把请求继续发给已经挂掉的后端。 - 连接复用:开启
keepalive,减少每次请求都新建连接的开销。没有 keepalive 的高并发场景,后端端口容易被 TIME_WAIT 占满。 - 文件描述符与连接数:
worker_connections、系统 ulimit、后端连接池上限要一起看。Nginx 报错too many open files时,调大 Nginx 配置之前,先看系统和进程的句柄数上限。 - 发布与回滚:502 经常出现在刚发布之后,先用
nginx -t检查配置语法,再用nginx -s reload平滑加载,避免直接重启造成短暂中断。
nginx -t
nginx -s reload
五、一个可直接套用的排查清单
| 现象 | 先看什么 | 最可能的原因 |
|---|---|---|
| 502,耗时很短 | error_log、上游进程 | 后端挂了、端口或地址配错 |
| 502,间歇出现 | max_fails、后端连接数 | 后端连接池满、偶发崩溃 |
| 504,耗时卡在超时值 | 上游耗时、慢查询日志 | 后端处理慢、外部接口慢 |
| 504,只在个别接口出现 | 该接口的耗时分布 | 特定接口的慢 SQL 或大文件处理 |
总结一句话:502 先查连接和进程,504 先查耗时和慢日志;先定性再调参,先修后端再调 Nginx。把日志、上游状态码和上游耗时这三项固定下来,大多数 502/504 都能在十分钟内定位到责任方。
- 点赞
- 收藏
- 关注作者
评论(0)