Nginx 502 和 504 到底差在哪:从 upstream 日志到超时参数的排查顺序
先分清两个错误码的含义
Nginx 作为反向代理时,502 Bad Gateway 表示它连上了上游,但拿到的响应不合法或连接被对端关闭;504 Gateway Timeout 表示它已经发出请求,但在规定时间内没等到响应。一个是「响应坏了」,一个是「响应没来」,处理方向完全不同。
还有一种容易被忽略的情况:Nginx 连上游的 TCP 连接都建不起来,这时返回的也是 502,但错误日志里是 connect() failed,和「应用崩了」是两回事。
第一步:打开 upstream 日志,别再猜
默认的 access log 只记录状态码,看不出上游发生了什么。加一个带 $upstream_* 变量的日志格式,信息量立刻不一样:
log_format upstream '$remote_addr [$time_local] "$request" $status '
'upstream=$upstream_addr status=$upstream_status '
'time=$upstream_response_time '
'connect=$upstream_connect_time '
'bytes=$body_bytes_sent';
access_log /var/log/nginx/upstream.log upstream;
关键看三列:upstream_status 是上游真实返回码,upstream_response_time 是上游处理耗时,upstream_connect_time 是建连耗时。如果 upstream_status 是 502 而 time 很短,说明上游直接拒绝或崩溃;如果 time 接近超时阈值,那就是 504 的典型特征。
多个上游时这些变量会用逗号分隔,和 upstream_addr 一一对应,重试过的请求能看出第一次打到了哪台。
第二步:区分连接失败、读超时、写超时
错误日志里的关键字直接对应不同参数:
grep -E 'upstream|timed out' /var/log/nginx/error.log | tail -50
connect() failed (111: Connection refused) while connecting to upstream
upstream timed out (110: Connection timed out) while reading response header from upstream
upstream timed out (110: Connection timed out) while sending request to upstream
三种情况分别对应 proxy_connect_timeout、proxy_read_timeout、proxy_send_timeout。默认都是 60 秒,很多人一看到 504 就把 proxy_read_timeout 调到 300 秒,结果只是把「快速失败」变成「慢速失败」,用户等得更久,问题还在。
正确做法是先确认上游到底慢在哪:数据库慢查询、外部接口、还是 GC。Nginx 的超时只是兜底,不是修复手段。
第三步:检查上游本身的状态
如果错误日志是 Connection refused,先在 Nginx 所在机器上直接验证:
ss -lntp | grep 8080
curl -sv --max-time 5 http://127.0.0.1:8080/healthz
连不上通常是进程没起来、只监听了 127.0.0.1 而 Nginx 走的是内网 IP、或者端口被防火墙拦了。Connection reset by peer 则多见于应用主动关闭长连接、或者 request body 太大被上游拒绝。
容器环境还要注意两件事:上游 Pod 重启导致 IP 变化,以及 DNS 缓存。用 proxy_pass http://backend; 配合 resolver 时,Nginx 只在启动时解析一次域名;后端扩容或漂移后,请求会打到旧地址。这类问题表现为「部分请求 502、部分正常」,很有迷惑性。
参数怎么调才不背锅
推荐的组合是:连接超时短、读超时按业务最长耗时设置、并且开启重试:
location /api/ {
proxy_connect_timeout 3s;
proxy_send_timeout 10s;
proxy_read_timeout 30s;
proxy_next_upstream error timeout http_502 http_503;
proxy_next_upstream_tries 2;
proxy_pass http://backend;
}
连接超时设短一点,能让故障机器快速被跳过;读超时按 P99 设,不要凭感觉给 300 秒。注意 proxy_next_upstream 对非幂等请求有风险,POST 重试可能造成重复下单,这类接口要单独排除。
另外,client_max_body_size 太小会让上传直接 413,但某些客户端会把 413 显示成 502,排查时别漏掉。
监控上该盯什么
只对 5xx 总数告警不够,建议把 upstream_status 和 upstream_response_time 一起采集:502 突增通常是上游发布或崩溃,504 突增通常是慢查询或外部依赖。两者分开看,能省掉大量「重启试试」的时间。
最后记住一个顺序:先看 upstream 日志确认是连接失败还是超时,再看错误日志定位到具体参数,最后才去查应用和依赖。调大超时永远放在最后一步。
- 点赞
- 收藏
- 关注作者
评论(0)