2、基础恢复策略:TCP重传机制(超时重传、快速重传)、TCP序列号与确认号的作用

丢包了怎么办?这是网络工程师每天都要面对的问题。TCP 作为传输层的"老大哥",它的恢复策略其实就两个核心武器:重传和确认。说白了,就是"没收到就再发一次,但怎么发、什么时候发,这里面门道很深"。

我刚开始做网络运维那会儿,遇到一个跨洋链路的丢包问题,业务方天天投诉文件传输慢。我抓了包一看,好家伙,RTO(超时重传时间)设置得乱七八糟,每次丢包都要等好几秒才重传。后来我调了参数,问题立马解决了。嗯,这就是我们今天要聊的基础恢复策略。

2.1 TCP序列号与确认号:通信的"坐标系统"

先别急着看重传,我们得先搞懂 TCP 是怎么知道"丢了哪个包"的。答案就在序列号和确认号里。

  • 序列号(Sequence Number):每个字节都有自己的编号。比如发送方要发 1000 字节,序列号从 1 开始,那第一个字节是 seq=1,最后一个字节是 seq=1000。
  • 确认号(Acknowledgment Number):接收方告诉发送方"我已经收到了哪些字节"。确认号 = 下一个期望收到的字节序号。

举个例子。我发 seq=1 的数据包,长度 100 字节。接收方收到后,回复 ack=101,意思就是"1-100 我都收到了,你从 101 开始发吧"。如果中间丢了 seq=50 的包,接收方会一直回复 ack=50,直到收到为止。

核心逻辑:序列号标记"发了什么",确认号标记"收到了什么"。两者配合,TCP 才能精确知道哪个包丢了。

我在项目中遇到过一种情况:客户端和服务器的序列号初始值(ISN)没有随机化,导致旧连接的数据包干扰了新连接。后来我强制开启了 ISN 随机化,问题才解决。你想想看,如果序列号不随机,攻击者很容易伪造 RST 包切断连接,这就是安全问题了。

2.2 超时重传(RTO):最朴素的恢复策略

超时重传,顾名思义,就是发送方等了一段时间没收到确认,就认为包丢了,重新发送。这个"等的时间"就是 RTO(Retransmission Timeout)。

RTO 怎么算?TCP 会动态测量 RTT(往返时间),然后根据 RTT 的波动来调整 RTO。公式大致是:

RTO = SRTT + max(G, 4 * RTTVAR)

其中 SRTT 是平滑后的 RTT,RTTVAR 是 RTT 的方差,G 是时钟粒度。说白了,RTO 要比平均 RTT 大一些,留出余量。

但这里有个坑:RTO 不能太小,也不能太大。太小了,网络稍微抖动一下就触发重传,造成拥塞;太大了,丢包后要等很久才恢复,用户体验极差。

避坑指南:我曾经在一条高延迟链路上(RTT 约 300ms)把 RTO 设成了 500ms,结果频繁触发超时重传,导致网络拥塞崩溃。后来我参考了 RFC 6298,把 RTO 下限设为 1 秒,问题才缓解。记住:RTO 下限建议 1 秒,上限建议 60 秒。

2.3 快速重传:更聪明的恢复策略

超时重传有个明显的缺点:要等。如果 RTO 是 1 秒,那丢包后就要等 1 秒才能恢复。对于实时性要求高的场景,这太慢了。

快速重传的思路是:利用重复确认来提前感知丢包。接收方收到乱序包时,会重复发送上一个期望的确认号。发送方收到 3 个重复确认(DupACK)后,就认为包丢了,立即重传,不用等超时。

举个例子:

  1. 发送方发了 seq=1, 2, 3, 4, 5
  2. 接收方收到了 seq=1, 2, 4, 5(seq=3 丢了)
  3. 接收方回复 ack=3, ack=3, ack=3(重复确认)
  4. 发送方收到 3 个 ack=3,立即重传 seq=3

你看,整个过程不需要等超时,效率高多了。我在做数据中心网络优化时,把快速重传的阈值从 3 改成了 2,对某些敏感业务确实有提升,但要注意:阈值太低容易误判,反而浪费带宽。

小技巧:快速重传的阈值(dupthresh)默认是 3,但你可以根据网络状况调整。如果链路质量好,可以降到 2;如果链路抖动大,建议保持 3 或更高。

2.4 超时重传 vs 快速重传:对比与选择

特性 超时重传(RTO) 快速重传(Fast Retransmit)
触发条件 超时未收到确认 收到 3 个重复确认
恢复速度 慢(依赖 RTO 计算) 快(无需等待)
适用场景 严重丢包、网络中断 轻度丢包、乱序
对拥塞的影响 可能加剧拥塞 配合拥塞控制,影响较小
实现复杂度 低 中

你可能会问:既然快速重传这么好,为什么还要超时重传?原因很简单:快速重传依赖重复确认,如果丢包严重到连确认包都丢了,那快速重传就失效了。这时候只能靠超时重传来兜底。

2.5 知识体系:TCP 重传机制全景图

下面这张图展示了 TCP 重传机制的核心逻辑,包括序列号/确认号的作用、超时重传和快速重传的触发条件与流程。

TCP 重传机制全景图 TCP 重传机制全景图 发送方 接收方 序列号 & 确认号 标记字节位置 精确感知丢包 超时重传 等待 RTO 超时 未收到确认 快速重传 收到 3 个重复确认 立即重传 未收到确认 重复确认 兜底策略 快速重传失效时,超时重传兜底

从这张图可以看出,TCP 的重传机制是一个分层体系:序列号/确认号是基础,快速重传是主力,超时重传是兜底。三者配合,才能在各种网络环境下保证数据的可靠传输。

2.6 实战建议与避坑指南

  • 监控 RTO 和重传率:我建议你在网络设备上持续监控这两个指标。如果重传率超过 1%,就要排查原因了。
  • 调整 RTO 参数:对于高延迟链路(如卫星通信),适当增大 RTO 下限;对于低延迟链路(如数据中心),可以适当减小 RTO 下限。
  • 注意快速重传的误判:网络乱序也可能触发重复确认。我曾经遇到过交换机负载均衡导致包乱序,触发了大量快速重传,浪费了带宽。后来我调整了负载均衡策略,问题才解决。
  • 序列号回绕问题:TCP 序列号是 32 位的,高速传输时可能回绕。Linux 内核已经处理了这个问题,但如果你自己实现协议栈,一定要小心。

一句话总结:超时重传是"等不到就重发",快速重传是"感觉丢了就重发"。两者结合,TCP 才能在丢包时快速恢复,又不浪费带宽。