Nginx 504 超时、499 一堆?网关排查法

页面转圈十几秒,最后甩出「504 Gateway Time-out」;打开访问日志,又发现一排没人认识的 499。两个都像是"超时",但锅不在同一个人身上。这篇把 504 和 499 拆开,用四步定位到真正的慢点。

一、先分清 504 和 499 分别在说谁

很多人把这两个码混着看,结果越查越乱。区别其实很干脆:

  • 504 Gateway Time-out :Nginx 把请求转给后端后,等不到响应就放弃了。锅在后端或链路慢------后端还在处理,只是超过了 Nginx 的等待上限。
  • 499 :Nginx 自己发明的非标准码(Nginx 日志里才有,HTTP 标准里没有),含义是 client closed request ------请求还没返回,客户端先断开连接了。锅常常在"客户端等不及",而它等不及的原因,往往又是后端真的慢。

所以线上常见的一幕是:后端慢 → 客户端(或上游负载均衡、手机 App)先超时断开 → Nginx 记一条 499;如果客户端够有耐心等到 Nginx 自己超时,那就是 504。

结论:504 和 499 经常是同一个病根的两个表现,别当成两个独立故障查。

二、第 1 步:让日志说出"到底谁慢"

默认的 access log 看不出时间花在哪,先把三个时间字段加进 log_format:

nginx 复制代码
log_format timed '$remote_addr $request '
                 'rt=$request_time '
                 'urt=$upstream_response_time '
                 'us=$upstream_status '
                 'ua=$upstream_addr '
                 'st=$status';

access_log /var/log/nginx/access.log timed;

四个字段是排查的核心:

  • $request_time:Nginx 从收到第一个字节到发完响应的总耗时;
  • $upstream_response_time:Nginx 发给后端、到收完后端响应的时间;
  • $upstream_status:后端返回的状态码(可能多个,用逗号分隔,对应多次重试);
  • $upstream_addr:真正处理这次请求的后端地址(多实例时能定位到具体那台)。

reload 之后,用两行 awk 就能把慢请求捞出来:

bash 复制代码
# 按 upstream 耗时排序,看最慢的 20 条
awk -F'urt=' '{split($2,a," "); print a[1], $0}' access.log | sort -rn | head -20

# 统计 504/499 出现的频次与对应后端
grep -E ' (504|499) ' access.log | awk '{print $NF, $(NF-3)}' | sort | uniq -c | sort -rn

判读原则很直接:

  • rt 很大、urt 也很大 → 慢在后端,继续查后端;
  • rt 很大但 urt 很小甚至为 - → 慢在 Nginx 或客户端这一侧(大响应体、慢客户端、带宽打满)。

三、第 2 步:确认是"后端超时"还是"连接就不通"

看 error.log 的关键字,能一次分辨两种性质完全不同的 504:

bash 复制代码
grep -i 'upstream timed out' /var/log/nginx/error.log | tail -20
  • upstream timed out (110: Connection timed out) while reading response header from upstream
    → 连上了后端,但后端迟迟不吐响应头。这是后端处理慢,最常见。
  • upstream timed out (110: ...) while connecting to upstream
    → 连后端都连不上。这是网络或后端端口问题,不是慢,是通不通。
  • no live upstreams / connect() failed (111: Connection refused)
    → 后端进程挂了或连接池被打满。

紧接着核对生效的超时配置:

bash 复制代码
nginx -T | grep -E 'proxy_(connect|send|read)_timeout|keepalive'

三个超时的分工要分清:

指令 管的是什么
proxy_connect_timeout 与后端建立连接的等待上限
proxy_send_timeout 向后端发送请求的两次写操作间隔上限
proxy_read_timeout 等待后端返回响应的两次读操作间隔上限(504 最常撞的就是它)

四、第 3 步:直连后端,把 Nginx 摘出去

怀疑是 Nginx 就先绕开它。在 Nginx 机器上直连后端端口,用 curl 把耗时分段打出来:

bash 复制代码
curl -o /dev/null -s -w 'dns=%{time_namelookup} conn=%{time_connect} ttfb=%{time_starttransfer} total=%{time_total}\n' \
     http://10.0.0.12:8080/api/health
  • time_connect 就很大 → DNS 或 TCP 建连慢(网络层);
  • time_starttransfer(TTFB)大 → 后端处理慢(应用层);
  • total 远大于 ttfb → 响应体传输慢(带宽 / 大文件)。

**直连也是几十秒没响应 → 问题在后端,别在 Nginx 上折腾了。**这一步能省掉一半无效排查。

五、第 4 步:五类根因速查

  1. 后端自身慢 :慢 SQL、Full GC、下游接口拖累、锁等待。表现为 urt 持续偏大,504 集中在某些接口上($request 能看出规律)。
  2. 后端排队:worker 进程数不够、线程池 / 连接池打满,请求在 backlog 里排队。表现为并发一上来才超时,平时正常。
  3. Nginx 到后端的 keepalive 没配 :每个请求都重新建连,高并发下建连耗时叠加成超时。需要 upstream 里加 keepalive 64;,同时 proxy_http_version 1.1; + proxy_set_header Connection "";,三者缺一不可。
  4. 长任务同步等待 :数据导出、报表生成、大文件下载硬等几十秒。这类请求本就不该同步等,应该改成异步任务 + 轮询/回调。
  5. 超时阈值配反了 :客户端超时 < Nginx 超时 < 后端超时。任何一层率先放弃,就会记成 499 或 504。正确顺序是:客户端 > Nginx > 后端应用,让最早发现问题的层来报错。

六、避坑清单

  1. 只调大 proxy_read_timeout 是掩盖,不是解决------请求继续堆积,连接数、内存一起涨,只是爆炸时间往后推。
  2. proxy_read_timeout 要大于后端应用自身的超时,否则后端还在等下游,Nginx 已经先甩 504 了,日志里只剩一句超时。
  3. 504 和 499 别混着下结论:499 通常意味着客户端先走人,检查前端 axios / 网关 / SLB 的超时设置。
  4. 云负载均衡(SLB / ALB)也有空闲超时,通常比 Nginx 更短,客户端到 Nginx 这一段先在 SLB 断掉,Nginx 日志里就是 499。
  5. upstream_status 是逗号分隔的多个值时,说明发生了重试 ,每个值对应 upstream_addr 里的一个后端,能直接看出是哪台在拖后腿。
  6. 不要把 ping 当证据:ICMP 通不代表 8080 端口通,也不代表后端应用没卡死。
  7. 两次采样之间要看趋势:偶发 504 去查后端 GC 与慢查询;持续 504 先查后端进程/线程池是否已经饱和。

小结

排查顺序记成一句话:先看 access log 的 $request_time / $upstream_response_time 分清慢在谁身上 → 读 error.log 的 upstream timed out 关键字区分"慢"还是"不通" → 直连后端端口复现,把 Nginx 摘出去 → 按"后端慢 / 排队 / keepalive / 长任务 / 阈值配反"五类根因对症处理。超时从来不是 Nginx 的错,它只是第一个把问题喊出声的人。


--- 关注本号,每天一个实用运维知识点 ---

相关推荐
Android系统攻城狮3 小时前
Linux Gstreamer深度解析之gst_audio_ring_buffer_delay调用流程与实战(七十二)
linux·运维·服务器·gstreamer音视频·音视频进阶
快乐的韭菜根根4 小时前
ubuntu 安装slurm并配置
linux·运维·ubuntu
U-Mail邮件系统4 小时前
自建邮箱服务器有哪些软件?三款主流邮件服务器软件推荐
运维·服务器
天远数科6 小时前
零信任架构实战:基于天远贷前风险报告构建自动化消金信贷风控与多头共债排查网关
运维·人工智能·架构·自动化
别动我齐刘海7 小时前
Linux 系统调试学习2
linux·运维·c++·人工智能·学习·机器学习·机器人
honsor7 小时前
机房IP化改造首选:以太网温湿度传感器,PoE供电+Modbus TCP一网搞定
linux·运维·服务器
星创易联7 小时前
PLC数据采集与远程运维平台:从边缘计算到集中监控
大数据·运维·边缘计算
郭老二8 小时前
【docker】docker compose使用,已nginx为例
nginx·docker·容器
寻道模式9 小时前
【运维心得】完整教程:绕过Win11限制让老机焕发新生
运维·操作系统·win11