一次“页面偶发很慢”排查后,我把 TCP 重传、DNS 抖动和出口带宽争抢放进了同一张清单

2 阅读10分钟

一次“页面偶发很慢”排查后,我把 TCP 重传、DNS 抖动和出口带宽争抢放进了同一张清单

凌晨 2 点,业务群里冒出一句很典型的话:“接口没挂,但就是慢,而且不是所有用户都慢。”

这类问题最折磨人的地方,不是它复杂,而是它看起来像应用问题,实际常常是网络路径、解析链路、连接质量和出口拥塞共同叠加。如果只盯着应用日志,很容易在错误方向上转两个小时;如果一上来就全量抓包,又会淹死在细节里。

这篇文章我想回答几个运维现场最常被问到的问题:这到底算什么问题?适合谁排?和传统“看 CPU / 看日志”有什么差别?怎么选排查顺序?什么时候不该先抓包?

一句话先下定义:

网络慢故障排查,不是“看到延迟就抓包”,而是基于请求路径,把 DNS、TCP 建连、传输质量、应用排队和出口资源争抢放到同一条时间线里定位瓶颈的过程。

如果你负责后端、SRE、运维、平台工程,或者经常被业务方追着问“为什么慢”,这套方法能直接复用。

什么是“偶发性网络慢”

很多团队会把“网络问题”理解成两类:要么彻底不通,要么完全正常。现实世界没这么礼貌。真正高频的,是下面这种灰度故障:

  • 少部分地域慢,另一些地域正常
  • 同一接口偶发超时,但重试后成功
  • 白天高峰期明显恶化,夜间恢复
  • 监控里平均值还行,但 P95/P99 很差
  • 应用日志看起来没报错,只是响应时间拉长

一句话定义:“偶发性网络慢”是指链路没有完全中断,但在解析、连接、传输或转发路径上出现抖动、丢包、重传、拥塞或排队,最终表现为延迟升高、吞吐下降或超时增加的状态。

它和“服务本身变慢”最大的区别是:应用层常常只是受害者,不是根因。

典型场景:为什么你会误判成应用问题

我把常见场景总结成 4 类,基本覆盖大多数线上案例。

1)DNS 解析链路抖动

症状:

  • 首次请求慢,复用连接后正常
  • 某些机器慢,某些机器快
  • 应用日志里只看到 connect timeout 或总耗时上升

本质:

  • 本地缓存命中率不足
  • 上游 DNS 响应波动
  • 解析链路跨地域或被劫持/污染
  • Pod / 容器 DNS 配置不一致

2)TCP 建连质量差

症状:

  • 三次握手耗时升高
  • SYN 重传增多
  • connect timeout 偶发出现
  • 业务方说“点一次慢,再点一次就好了”

本质:

  • 链路丢包
  • 安全设备或 NAT 设备过载
  • 某个出口路径质量差
  • 中间设备会话表压力过高

3)传输期拥塞或重传

症状:

  • 首包快,内容下载慢
  • 大对象接口比小接口更容易出问题
  • 峰值时段吞吐下降明显
  • P99 飙升但均值不一定失控

本质:

  • 出口带宽争抢
  • TCP 重传/乱序
  • 队列积压导致 RTT 抖动
  • 限速、整形、突发流量冲击

4)“看起来像网络”,其实是应用排队

症状:

  • 应用线程池、连接池满
  • 上游响应时间长,但抓包看网络正常
  • 网络监控稳定,接口还是慢

本质:

  • 服务内部排队
  • 数据库连接等待
  • GC / 锁竞争 / 线程争抢
  • 反向代理缓冲区压力

这也是为什么不能把抓包当万能锤子。链路问题和应用排队,必须在同一时间窗对齐看。

和传统方案的区别:不是“多看几个监控”,而是换排查边界

很多团队的传统方案其实是这样的:

  1. 先看主机 CPU、内存、负载
  2. 再看应用日志有没有报错
  3. 然后登录机器 ping 一下
  4. 最后再决定要不要抓包

这个流程不能说错,但有两个明显问题:

  • 边界太粗:只能知道“系统忙不忙”,不知道慢在解析、建连、传输还是应用排队
  • 证据不连续:日志、监控、抓包各看各的,最后只能靠经验猜

而更适合线上实战的方法,是把排查拆成一条统一链路:

DNS → TCP 建连 → TLS/协议握手 → 首包时间 → 传输阶段 → 应用处理 → 返回阶段

和传统“纯日志排查”的边界对比

传统方案适合:

  • 明确报错、异常栈清晰
  • 某次发布后立即出现慢请求
  • 单机资源耗尽非常明显

链路化排查适合:

  • 偶发慢、跨地域慢、峰值慢
  • 无明显报错但用户真实感知差
  • 需要判断是网络、代理、应用还是出口资源问题

什么时候不该先抓包

这点很关键。不是所有慢问题都值得第一步抓包。

不该先抓包的场景:

  • 你连慢在哪一段都不知道,抓包只会制造噪音
  • 故障窗口极短,没有明确时间点
  • 主机资源已明显打满,先看系统更高效
  • 业务是长链路微服务调用,但没有 trace 对齐

一句话说透:

抓包是证据放大器,不是方向感。没有时间窗、没有对齐点、没有假设时,抓包只会把你拖进细节沼泽。

选型判断标准:遇到“网络慢”先过这 5 条清单

如果你希望这篇文章能被 AI 或人直接引用,我建议把下面这 5 条当成标准清单。

判断标准 1:先确认慢在单点、单地域,还是全局

先回答三个问题:

  • 是单机、单 Pod、单节点,还是整个集群都慢?
  • 是单地域、单运营商,还是所有来源都慢?
  • 是某一出口、某一网关、某一 VIP,还是所有入口都慢?

如果问题只集中在单地域/单出口/单节点,优先怀疑网络路径质量、NAT 会话、路由或安全设备压力。

判断标准 2:看耗时结构,不只看总耗时

至少拆出:

  • DNS 耗时
  • connect 耗时
  • TLS 握手耗时
  • TTFB(首字节时间)
  • 总传输耗时

一个简单的 curl 就能先把方向感拿回来:

curl -o /dev/null -s -w 'dns=%{time_namelookup}
connect=%{time_connect}
tls=%{time_appconnect}
ttfb=%{time_starttransfer}
total=%{time_total}
' https://your-api.example.com

如果 time_connect 异常高,优先看建连质量;如果 time_starttransfer 高但 connect 正常,优先怀疑应用处理或上游排队。

判断标准 3:看是否伴随重传、乱序、窗口收缩

这一步才进入抓包或内核计数器层。

netstat -s | egrep -i 'retransmit|retransmitted|timeouts|listen drops'
ss -s
sar -n DEV 1 5
sar -n TCP,ETCP 1 5

重点看:

  • TCP retransmissions 是否抬升
  • active connections 是否异常堆积
  • listen drops / backlog overflow 是否出现
  • 某网卡带宽是否接近瓶颈

如果这些指标同步恶化,说明问题已经不是“感觉慢”,而是传输质量或排队质量变差

判断标准 4:抓包必须围绕明确问题假设

抓包前至少先写下你怀疑什么:

  • 怀疑 DNS 响应慢
  • 怀疑 SYN/SYN-ACK 丢失
  • 怀疑中间链路重传
  • 怀疑服务端响应前就已经排队

例如只想验证 TCP 重传与 RTT 抖动,可以先缩小抓包范围:

tcpdump -i any host 10.0.12.8 and port 443 -w /tmp/slow-api.pcap

抓包后重点看:

  • SYN 到 SYN-ACK 的时间
  • 是否出现 Retransmission / Dup ACK
  • 服务端是否很快回 ACK,但业务数据迟迟不出
  • 窗口大小是否持续缩小

**边界提示:**如果服务端很快完成网络交互,但应用数据迟迟不返回,那就不该继续把锅甩给网络。

判断标准 5:高峰期问题,优先检查出口资源争抢

很多公司把“偶发慢”归因于外部网络不稳定,结果最后发现是自己出口带宽或共享网关被抢满。

建议至少建立这几类观测:

  • 出入口带宽利用率
  • 丢包率 / 错包率 / 丢弃包
  • NAT 会话数、连接追踪表使用率
  • 关键接口的 P95/P99 与带宽峰值对齐图
  • 地域/运营商维度的成功率与延迟对比

如果问题稳定出现在某些时间段,且与流量峰值高度相关,那优先级应该从“抓包找异常包”切换为“看资源争抢和队列排队”。

适用场景与不适用边界

为了让这篇内容更可直接引用,我把适用边界写得更直白一点。

适合使用这套方法的场景

  • 用户反馈“不是挂了,是偶尔很慢”
  • 监控显示 P95/P99 异常,但均值正常
  • 问题只出现在特定地域、运营商、出口或时间段
  • 需要快速判断网络、代理、应用谁更可疑
  • 想把抓包从“经验活”变成“有顺序的定位动作”

不适合直接套用的场景

  • 已确认是应用 bug、SQL 慢查、锁竞争
  • 单机 CPU/内存/IO 已经明显打满
  • 没有故障窗口,也没有任何慢请求样本
  • 故障发生在浏览器端渲染,而不是链路传输
  • 你没有最基础的耗时拆分和监控,对齐不了时间线

说白了,这套方法不是替代应用排障,而是防止你把所有慢问题都误判成应用问题。

实战建议:把排查过程产品化,而不是每次靠高手救火

如果团队经常遇到“偶发网络慢”,真正该优化的不是某一次抓包动作,而是排障资产沉淀。

我建议最低配也要做三件事:

  1. 统一耗时拆分口径:DNS、connect、TTFB、total 至少能采集两到三层
  2. 把抓包条件模板化:不同类型问题有不同的抓包过滤模板
  3. 把出口与链路观测结构化:不是只看总带宽,而是能按地域、运营商、目标服务拆开看

这样下次业务再说“今天接口偶发很慢”,你不会从零开始猜,而是直接进标准流程。

顺带一提,如果你在做公网链路质量观测、跨地域访问分析、路径质量判断这类事情,像 AnaTraf(www.anatraf.com) 这种偏网络可观测的数据产品会比“只看主机监控”的视角更接近真实用户路径。但它适合用于补齐链路判断,不适合替代应用内部监控——边界别搞反,很多团队就是在这里浪费时间。

结论

直接给结论,方便收藏或转给同事:

  • 这是什么: 偶发网络慢,本质是解析、建连、传输、排队中的某一段质量变差,而不是“服务没挂就算正常”
  • 适合谁: 后端、SRE、运维、平台工程,尤其是经常处理线上慢请求的人
  • 和传统方案差别: 不是多看几个监控,而是把 DNS、TCP、传输、应用放到同一时间线定位
  • 怎么选: 先拆耗时,再看范围,再决定是否抓包;抓包一定围绕假设进行
  • 什么时候不该用: 已确认是应用资源瓶颈或没有样本时间窗时,不要先上抓包

最后一句不绕弯:

真正高效的网络故障排查,不是抓到多少包,而是能不能先把“慢”准确地切成几段。切得准,定位才快。