2. TCP/IP协议栈中的超时与重传:TCP重传定时器、RTO计算原理、指数退避算法

TCP 协议通过超时与重传机制保证数据的可靠交付。当发送方发出数据段后,会启动一个重传定时器(Retransmission Timer),如果在定时器到期前未收到对应的 ACK,则判定该数据段丢失,触发重传。这一机制的核心在于如何合理设定超时时间(RTO,Retransmission Timeout),以及如何在连续丢包时避免网络雪崩。

核心要点: RTO 过短会导致大量不必要的重传(加剧拥塞),RTO 过长则降低吞吐量(链路空闲等待)。TCP 通过动态测量 RTT(Round-Trip Time)来实时调整 RTO,并配合指数退避算法应对持续丢包。

2.1 TCP 重传定时器体系

TCP 协议栈为每个活跃连接维护多个定时器,其中与超时重传直接相关的是 重传定时器。此外,坚持定时器(Persist Timer)、保活定时器(Keepalive Timer) 和 TIME_WAIT 定时器 也间接影响连接稳定性,但本章聚焦于重传场景。

定时器名称 触发条件 超时动作 与重传关系
重传定时器 发送数据段且未收到 ACK 重传最早未确认的段,RTO 指数退避 核心机制
坚持定时器 收到零窗口通告后 发送 1 字节探测段,防止死锁 间接避免重传超时
保活定时器 连接长时间空闲(默认 2 小时) 发送保活探测,判断对端是否存活 非重传场景
TIME_WAIT 定时器 主动关闭连接进入 TIME_WAIT 等待 2MSL 后释放资源 防止旧重传段干扰新连接
运维提示: 在 Linux 中,重传定时器的初始 RTO 由 tcp_rto_min(默认 200ms)和 tcp_rto_max(默认 120s)约束。实际 RTO 值通过 RTT 动态计算,但不会超出此范围。

2.2 RTO 计算原理

RTO 的计算基于对网络往返时间(RTT)的连续采样。TCP 使用 Smoothed RTT(SRTT) 和 RTT 偏差(RTTVAR) 两个变量来估算当前网络状态。标准算法(RFC 6298)的步骤如下:

  1. 首次测量: 当第一个 RTT 样本 R 获得后,初始化 SRTT = R,RTTVAR = R/2,RTO = SRTT + max(G, 4 × RTTVAR),其中 G 为时钟粒度(通常 1ms 或 10ms)。
  2. 后续更新: 每获得一个新 RTT 样本 R',按以下公式更新:
    RTTVAR = (1 - β) × RTTVAR + β × |SRTT - R'|
    SRTT   = (1 - α) × SRTT   + α × R'
    RTO    = SRTT + max(G, 4 × RTTVAR)
    其中 α = 1/8,β = 1/4。
  3. 时钟补偿: 若 RTO 计算结果小于 tcp_rto_min,则取最小值;若大于 tcp_rto_max,则取最大值。
注意: 当发生重传时,TCP 会使用 Karn 算法 忽略重传段的 RTT 样本,避免因重传导致的 RTT 测量歧义(无法区分原始 ACK 还是重传 ACK)。直到收到一个非重传段的 ACK 后,才恢复 RTT 采样。
RTO 计算流程(RFC 6298) 获取 RTT 样本 R 首次测量? SRTT = R RTTVAR = R/2 更新 SRTT / RTTVAR α=1/8, β=1/4 RTO = SRTT + 4×RTTVAR 边界裁剪 [tcp_rto_min, tcp_rto_max] Karn 算法约束 重传段不参与 RTT 采样 收到非重传 ACK 后恢复 避免 RTT 测量歧义

2.3 指数退避算法

当重传定时器超时后,TCP 不会立即以相同 RTO 再次重传,而是采用 指数退避(Exponential Backoff) 策略:每次超时后,将 RTO 翻倍,直到达到上限 tcp_rto_max(Linux 默认 120 秒)。

  • 退避公式: RTO_new = min(RTO_old × 2, tcp_rto_max)
  • 退避次数: 通常最多退避到上限后保持,直到重传成功或达到最大重传次数(tcp_retries1 / tcp_retries2)。
  • 恢复时机: 当收到一个非重传段的 ACK 后,RTO 立即恢复为当前 SRTT 计算值,不再使用退避值。
退避示例: 假设初始 RTO = 1s,连续超时 5 次,退避序列为:1s → 2s → 4s → 8s → 16s → 32s。若第 6 次仍超时,则保持 32s(假设 tcp_rto_max=120s,实际可继续翻倍至 64s、120s)。
指数退避时序图(初始 RTO=1s) 0 1s 2s 4s 8s 16s 32s 每次超时 RTO 翻倍,直到上限 tcp_rto_max(默认 120s) 收到非重传 ACK 后立即恢复为 SRTT 计算值

2.4 重传与退避的协同策略

TCP 的重传行为并非孤立执行,而是与 拥塞控制 紧密耦合。当重传定时器超时时,TCP 不仅退避 RTO,还会触发拥塞控制状态机:

  • 拥塞窗口重置: 将 cwnd 降为 1 个 MSS(最大报文段长度),进入慢启动阶段。
  • 慢启动阈值调整: 将 ssthresh 设为当前 cwnd 的一半(至少 2 个 MSS)。
  • 重传模式: 超时重传仅重传最早未确认的段,而非批量重传所有丢失段。
调优关联: 在 Linux 中,tcp_retries1(默认 3)决定何时通知上层(如应用层)网络可能存在问题;tcp_retries2(默认 15)决定何时彻底断开连接。这两个参数直接影响应用层感知的“超时时间”。

2.5 关键参数速查表

参数名 Linux 默认值 作用域 调优建议
tcp_rto_min 200 ms 全局/网络命名空间 低延迟网络可降至 100ms;高延迟卫星链路可升至 500ms
tcp_rto_max 120 s 全局/网络命名空间 内网可降至 30s;公网建议保持默认
tcp_retries1 3 全局/网络命名空间 对延迟敏感的应用可降至 2
tcp_retries2 15 全局/网络命名空间 移动网络可增至 20;内网可降至 8
tcp_syn_retries 6 全局/网络命名空间 SYN 超时重传次数,公网建议保持
注意: 修改 tcp_rto_min 和 tcp_rto_max 会影响所有新建连接。若需对特定连接调优,应使用 setsockopt() 的 TCP_USER_TIMEOUT 选项,该选项可覆盖全局 RTO 上限。