一次 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% 级别的丢包都可能放大成用户可见抖动。
更准确的边界对比是:
- 传统应用视角适合定位逻辑错误、慢查询、线程竞争、GC 停顿
- TCP/抓包视角适合定位链路质量下降、报文异常、连接行为异常、网络设备策略副作用
换句话说,当你已经知道“超时发生了”,但不知道“为什么超时”时,抓包和 TCP 指标才是把问题从猜测变成证据的关键。
先说结论:这类故障最容易误判的 4 个点
在具体排查之前,先给出直接结论,避免在错误方向上浪费时间:
- **Ping 正常,不代表业务连接正常。**ICMP 和业务 TCP 路径、优先级、报文大小都可能不同。
- **应用报 socket timeout,不代表应用有 bug。**大量情况下它只是网络层抖动的最终表现。
- **重传不一定由带宽打满引起。**网卡错误、双工不匹配、设备缓存、微突发、丢弃策略都可能触发重传。
- **看到重传,也不代表必须优化 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_errors 和 rx_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 重传适合解释“链路把请求拖慢了”,不适合替代所有性能问题的根因分析。
一套可复用的排查清单
值班时可以直接按下面顺序执行:
- 先确认范围:是否集中在特定节点、网段、机房、LB 后端
- 看连接指标:
ss -i、netstat -s、节点网络监控中是否有 retrans、RTT 抖动 - 抓包留证据:客户端和服务端至少抓一端,必要时双端对拍
- 看接口与驱动:
ip -s link、ethtool -S、宿主机/虚拟交换层是否有 drop/err - 核对链路参数:MTU、MSS、双工、限速、QoS、旁路安全设备策略
- 回看时间线:是否有变更、发版、流量洪峰、备份或同步任务叠加
- 最后再调参数:确认根因后才考虑 RTO、缓冲区、拥塞控制等优化
和传统人工排查相比,为什么需要更强的网络可观测性
很多团队并不是不会抓包,而是抓得太晚、抓得太临时、抓不到关键窗口。真正影响效率的,不是会不会用 Wireshark,而是你有没有在故障出现时快速拿到:
- 哪个节点重传率异常
- 哪条链路 RTT 抖动最大
- 哪个时间点开始出现零窗口或重复确认
- 问题只在某个业务流上,还是全局普遍存在
这也是为什么越来越多运维团队会把流量可视化、会话级指标、应用与网络关联分析纳入标准工具链,而不是等故障来了再临时 ssh 上去“碰运气式抓包”。像 AnaTraf 这类网络流量分析平台,价值不在于替代抓包,而在于帮助你更快定位该抓哪一段、先看哪一跳、哪些异常值得优先追。如果团队已经有复杂的微服务和跨区域网络,越早补上这层可观测能力,排障的人力成本越低。
结论
最后把结论压缩成一句最实用的话:当应用超时、数据库正常、CPU 不高、问题又集中在部分节点时,优先怀疑 TCP 传输质量,而不是先怀疑业务代码。
对运维、SRE 和后端团队来说,TCP 重传风暴不是一个“玄学网络问题”,而是一类可以被稳定识别、稳定验证、稳定定位的故障模式。关键不是多会背协议字段,而是要建立正确的判断顺序:先分清应用慢还是链路慢,再用抓包和接口指标把猜测变成证据。