TCP重传发生在内核层,应用层send/recv成功不代表数据已送达对端;重传是自愈机制而非故障信号,常见于高延迟或低丢包链路,不影响请求超时但会抬高RTT、降低吞吐。

为什么 tcpdump 看到大量 Retransmission,但应用层完全没感知?
根本原因:TCP 重传发生在内核协议栈,而应用层调用 send() 或 recv() 成功返回,不代表数据已送达对端——只要连接未断、内核还能重试,应用就可能一直“正常”运行。Retransmission 是 TCP 自愈机制的体现,不是故障信号本身。
常见错误现象:tcpdump -i eth0 'tcp[tcpflags] & (tcp-rst|tcp-syn) != 0' 没抓到 RST,ss -i 显示大量 retrans 字段增长,但客户端 HTTP 请求耗时稳定、日志无 ERROR。
- 典型场景:后端服务部署在高延迟或丢包率 1–3% 的跨机房链路,TCP 启用了
tcp_retries2(默认 15 次),单次重传间隔从 200ms 指数增长到数秒,整体请求仍落在超时阈值内 - 关键参数差异:
/proc/sys/net/ipv4/tcp_retries2控制重传上限,/proc/sys/net/ipv4/tcp_rmem影响接收窗口大小——窗口太小会触发虚假重传(dup ack 被误判为丢包) - 性能影响:重传本身不卡应用线程,但会抬高 RTT 估算值(
ss -i中的rtt和rttvar),进而降低拥塞窗口(cwnd),长期看吞吐下降
如何确认是真实丢包还是路径 MTU / 分片问题?
Retransmission 不等于链路丢包——IP 层分片失败、中间设备禁止 ICMP “Fragmentation Needed” 报文、或 TCP MSS 协商异常,都会导致 SYNs 或数据包被静默丢弃,触发重传。
实操建议:
- 用
ping -M do -s 1472 x.x.x.x测试路径 MTU(1472 + 20IP + 8ICMP = 1500),若不通,逐步减小-s值;对比tcpdump中 SYN 包的MSS选项(如tcp[20:2]偏移处)是否明显小于探测值 - 检查是否有
iptables -A OUTPUT -p icmp --icmp-type fragmentation-needed -j DROP类规则,这类规则会让 PMTU 发现失效 - 抓包时加
-f参数(tcpdump -f)避免截断,确认重传包是否全是相同序列号(真丢包)还是混有不同 seq(可能是乱序+dup ack 误触发)
哪些 Retransmission 可以安全忽略?
Linux 内核在特定条件下会生成“良性重传”,不反映网络恶化,也不影响业务 SLA。
- SYN 重传:客户端快速重试(
tcp_syn_retries默认 6),只要第三次 SYN-ACK 回来得及,上层 connect() 就不会超时 - TIME-WAIT 状态下的 FIN 重传:对端已关闭连接,本端仍在重发 FIN,
ss -tan state fin-wait-1 | wc -l高但持续时间短,属正常回收行为 - 零窗口探测(ZeroWindowProbe)被误标为 retransmission:当接收方通告窗口为 0,发送方按
tcp_probe_interval定期发 1 字节探测,Wireshark 有时将其归类为重传,实际不是
验证方法:用 ss -i sport = :8080 查看具体连接的 retrans 计数,再结合 tcpretrans(bpftrace 工具)过滤出真正因丢包触发的重传事件,排除 probe/SYN/FIN 类型。
应用层无超时 ≠ 网络没问题,下一步该盯什么?
最易被忽略的是重传背后的时序挤压效应:即使单次请求不超时,高频小包重传会推高队列延迟(qdisc drop / pfifo_fast 排队),让后续请求的首字节延迟(TTFB)波动加剧,P99 毛刺变多,但平均值照旧。
必须交叉验证:
- 查
/proc/net/snmp中Tcp:行的RetransSegs(重传段数)和OutSegs(发出段数),比值 > 0.5% 就需干预 - 用
ethtool -S eth0 | grep -i "err\|drop\|fifo"看网卡驱动层丢包,区分是网络问题还是本机处理不过来 - 对比同一路径上 UDP 流量(如
iperf3 -u)的丢包率——如果 UDP 丢包率接近 0,而 TCP 大量重传,基本可锁定是 TCP 参数或中间设备策略问题
复杂点在于:重传可能只发生在某个方向(如服务端向客户端发响应时重传),而客户端发请求一切正常,此时 tcpdump 必须在服务端出接口抓,不能只在客户端看。










