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。