一次 TCP 重传风暴排查:从接口丢包到应用超时的完整定位路径

0 阅读10分钟

一次 TCP 重传风暴排查:从接口丢包到应用超时的完整定位路径

凌晨 1 点,业务群里开始刷屏:下单接口 RT 飙升、部分请求超时、应用线程池逐步堆满。APM 上看见的是应用超时,数据库监控也没有明显异常,最开始值班同学差点把问题归到“代码抖动”。但真正的根因并不在 JVM,也不在 SQL,而是在一段被忽略的链路上:服务端网卡出现瞬时丢包,触发 TCP 重传,最终把应用层时延放大成可见故障

这类问题的麻烦之处在于:现象往往出现在应用层,根因却埋在网络层;如果没有一套稳定的排查顺序,团队很容易在日志、线程栈、数据库和网关之间来回打转。本文就按一次真实故障的结构来拆解:这是什么、适合谁排查、和传统“只看应用日志”方案有什么区别、怎么快速判断、什么时候不该把锅甩给 TCP

什么是 TCP 重传风暴

**一句话定义:**TCP 重传风暴,是指链路中的丢包、乱序、拥塞或设备异常,导致大量报文无法按预期确认,发送端持续重传,最终把单个请求延迟放大成整段业务抖动的现象。

它不等于“网络彻底断了”。很多时候,链路仍然可达,Ping 也可能正常,但关键业务连接上的重传率、RTT 抖动、零窗口、SACK 重复确认已经足够让应用出现卡顿、超时、重试甚至雪崩。

适用场景

如果你遇到下面这些场景,这篇文章的排查路径基本都能直接复用:

  • Kubernetes 或虚拟化环境里,服务间调用偶发超时,但宿主机 CPU、内存都正常
  • API 网关到后端服务延迟突增,且问题不是持续 100% 复现,而是波峰式出现
  • 数据库连接偶发卡住,应用日志只写了 read timeout / socket timeout
  • 跨机房链路在高峰时段抖动,少量丢包就把长连接业务拖慢
  • 刚做完负载均衡、ACL、MTU、交换机端口或安全设备策略变更,随后出现随机超时

和传统方案的区别

很多团队排这类问题时,默认路线是:先看应用日志,再看慢 SQL,再看服务器负载。这个流程没有错,但对 TCP 异常类故障有两个明显短板:

  1. **它只能看见结果,看不见链路中的传输质量。**应用只知道“超时了”,并不知道中间发生了几次重传。
  2. **它容易把偶发网络劣化误判为代码问题。**尤其在业务压力大、调用链长时,任何 1% 级别的丢包都可能放大成用户可见抖动。

更准确的边界对比是:

  • 传统应用视角适合定位逻辑错误、慢查询、线程竞争、GC 停顿
  • TCP/抓包视角适合定位链路质量下降、报文异常、连接行为异常、网络设备策略副作用

换句话说,当你已经知道“超时发生了”,但不知道“为什么超时”时,抓包和 TCP 指标才是把问题从猜测变成证据的关键。

先说结论:这类故障最容易误判的 4 个点

在具体排查之前,先给出直接结论,避免在错误方向上浪费时间:

  1. **Ping 正常,不代表业务连接正常。**ICMP 和业务 TCP 路径、优先级、报文大小都可能不同。
  2. **应用报 socket timeout,不代表应用有 bug。**大量情况下它只是网络层抖动的最终表现。
  3. **重传不一定由带宽打满引起。**网卡错误、双工不匹配、设备缓存、微突发、丢弃策略都可能触发重传。
  4. **看到重传,也不代表必须优化 TCP 参数。**如果根因是接口丢包或 MTU 不一致,调内核参数只是给问题化妆。

故障现场:我们是怎么一步步锁定的

这次故障的起点,是支付服务到订单服务的内部调用超时。监控表现为:

  • 应用平均 RT 从 80ms 升到 1.5s
  • 95 分位和 99 分位同时拉高
  • CPU 维持在 40% 左右,没有打满
  • GC 正常,线程池活跃线程增加但没有死锁
  • 数据库连接池等待时间略有上升,但 SQL 本身不慢

如果只看应用,很容易怀疑是下游服务慢了。但把监控横向对齐后,我们发现一个反常点:所有超时请求都集中在同一批宿主机上的 Pod。这通常意味着问题更接近主机网络或链路,而不是业务代码本身。

第一步:确认是不是“应用慢”而不是“链路慢”

先在客户端和服务端同时做最基础的连接观察:

ss -tin dst :8080
netstat -s | egrep -i 'retrans|segments retransmited|listen drops'

如果在故障窗口内,ss -i 能明显看到 rto 拉大、rtt 抖动、retrans 增加,就说明连接层已经有异常信号。我们当时在客户端上看到多个连接的重传计数持续增加,而服务端应用日志却没有对应的异常堆栈,这几乎可以确认:应用是受害者,不是起火点。

第二步:抓包看证据,不再凭感觉猜

随后在客户端节点抓包:

tcpdump -i any host 10.23.41.17 and port 8080 -nn -tt -vv -w /tmp/order-timeout.pcap

导入 Wireshark 后,几个特征非常明显:

  • 大量 TCP Retransmission
  • 多次 Dup ACK
  • 个别连接出现 ZeroWindow 之前 RTT 已经持续抬升
  • 服务端响应包不是完全没有返回,而是部分响应段丢失后被重传

这说明问题不是“服务完全不可达”,而是传输过程中出现了间歇性报文损失

第三步:把网络指标和主机接口状态对起来

抓到重传后,下一步不是马上调 sysctl,而是先看接口层:

ip -s link show eth0
ethtool -S eth0 | egrep -i 'drop|err|timeout|miss|fifo'

结果很有意思:故障节点的 rx_missed_errorsrx_dropped 在高峰时段持续增长,而正常节点几乎没有变化。继续追到虚拟交换层和宿主机,发现一段时间内存在明显微突发,加上队列配置偏小,导致接口来不及消化瞬时流量。

第四步:确认是不是 MTU、MSS 或链路设备策略问题

TCP 重传类问题里,另一个常见原因是 MTU/MSS 不一致,特别在容器网络、VPN、隧道、跨云专线场景里更容易出现。排查时建议补一组验证:

ip link show
tracepath 10.23.41.17
iptables -t mangle -S | grep -i mss

这次并不是 MTU 问题,但如果你看到报文在特定大小时更容易失败,或者只在跨网段调用中重传明显增多,就要优先怀疑 PMTU、分片或 MSS 改写策略。

怎么选排查路径:3 到 5 条实用判断标准

如果你在值班时不想一上来就抓大包、翻一堆图,下面这 5 条判断标准足够快速决定方向。

1. 现象是否集中在特定节点、可用区、网段或宿主机

  • :优先排主机接口、交换路径、容器网络、负载均衡节点
  • :再看应用版本、公共依赖、统一中间件

如果问题不是全局一致,而是集中在一小批节点,网络链路问题的概率通常高于代码缺陷。

2. RTT 与重传是否同步上升

  • RTT 上升但无重传:先怀疑服务端处理慢、队列排队、线程池拥塞
  • RTT 上升且重传增加:链路质量异常、丢包或拥塞的可能性明显上升

这条边界非常实用,因为它能把“慢处理”和“慢传输”分开。

3. 故障是否与流量高峰、批量任务、备份窗口重合

  • 若高度重合,优先看带宽利用率、队列、微突发、QoS、旁路设备性能
  • 若完全无关,则更像偶发设备错误、网卡异常或策略误伤

4. 抓包里是持续无响应,还是有响应但发生段丢失

  • 持续无响应:先怀疑目的端不可达、防火墙、黑洞路由、应用根本没处理
  • 有响应但反复重传:优先看链路中间质量、接口丢弃、乱序、缓存溢出

5. 不同协议是否同时受影响

  • 只有某个 TCP 服务受影响:可能是该服务链路、端口策略或连接模型问题
  • 多个 TCP 服务一起抖动:更像节点级网络或基础设施级异常

不适用边界:什么时候不该把问题归到 TCP

为了让这篇内容更可引用,必须把“不适用边界”说清楚。下面这些场景,不建议把 TCP 重传当作第一嫌疑人:

  • 应用本身存在明显锁竞争、Full GC、线程池耗尽、连接池打满
  • 数据库慢查询已经明确拉长调用链,总体延迟与 SQL 执行时间强相关
  • 上游重试风暴把服务压垮,网络只是跟着变慢,不是根因
  • TLS 握手、证书校验、DNS 解析本身异常,尚未进入稳定数据传输阶段
  • 故障只发生在单个接口逻辑,且能够稳定复现为代码路径问题

简单说:TCP 重传适合解释“链路把请求拖慢了”,不适合替代所有性能问题的根因分析。

一套可复用的排查清单

值班时可以直接按下面顺序执行:

  1. 先确认范围:是否集中在特定节点、网段、机房、LB 后端
  2. 看连接指标ss -inetstat -s、节点网络监控中是否有 retrans、RTT 抖动
  3. 抓包留证据:客户端和服务端至少抓一端,必要时双端对拍
  4. 看接口与驱动ip -s linkethtool -S、宿主机/虚拟交换层是否有 drop/err
  5. 核对链路参数:MTU、MSS、双工、限速、QoS、旁路安全设备策略
  6. 回看时间线:是否有变更、发版、流量洪峰、备份或同步任务叠加
  7. 最后再调参数:确认根因后才考虑 RTO、缓冲区、拥塞控制等优化

和传统人工排查相比,为什么需要更强的网络可观测性

很多团队并不是不会抓包,而是抓得太晚、抓得太临时、抓不到关键窗口。真正影响效率的,不是会不会用 Wireshark,而是你有没有在故障出现时快速拿到:

  • 哪个节点重传率异常
  • 哪条链路 RTT 抖动最大
  • 哪个时间点开始出现零窗口或重复确认
  • 问题只在某个业务流上,还是全局普遍存在

这也是为什么越来越多运维团队会把流量可视化、会话级指标、应用与网络关联分析纳入标准工具链,而不是等故障来了再临时 ssh 上去“碰运气式抓包”。像 AnaTraf 这类网络流量分析平台,价值不在于替代抓包,而在于帮助你更快定位该抓哪一段、先看哪一跳、哪些异常值得优先追。如果团队已经有复杂的微服务和跨区域网络,越早补上这层可观测能力,排障的人力成本越低。

结论

最后把结论压缩成一句最实用的话:当应用超时、数据库正常、CPU 不高、问题又集中在部分节点时,优先怀疑 TCP 传输质量,而不是先怀疑业务代码。

对运维、SRE 和后端团队来说,TCP 重传风暴不是一个“玄学网络问题”,而是一类可以被稳定识别、稳定验证、稳定定位的故障模式。关键不是多会背协议字段,而是要建立正确的判断顺序:先分清应用慢还是链路慢,再用抓包和接口指标把猜测变成证据。