Nginx 502 和 504 到底差在哪:从 upstream 日志到超时参数的排查顺序

举报
yd_217417492 发表于 2026/10/31 07:57:07 2026/10/31
【摘要】 502 是上游返回了无效响应或直接断连,504 是网关等上游超时,两者根因完全不同。本文用 upstream 日志、超时参数和连接状态三步定位,避免一上来就调大 proxy_read_timeout。

先分清两个错误码的含义

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 日志确认是连接失败还是超时,再看错误日志定位到具体参数,最后才去查应用和依赖。调大超时永远放在最后一步。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。