TCP拥塞控制#
一句话答案#
TCP 拥塞控制四个阶段:慢启动(指数增长)→ 拥塞避免(线性增长)→ 快重传(3 个重复 ACK 立即重传)→ 快恢复(窗口减半而非重置),核心原则是 AIMD(加性增、乘性减)。
核心要点
核心变量#
- cwnd(拥塞窗口):发送方维护,控制发送速率
- ssthresh(慢启动阈值):慢启动和拥塞避免的分界线
- 发送窗口 = min(cwnd, rwnd)
1. 慢启动(Slow Start)#
cwnd 从 1 MSS 开始,每收到一个 ACK → cwnd += 1
效果:每个 RTT cwnd 翻倍(指数增长)
当 cwnd >= ssthresh → 进入拥塞避免plaintext从 1 MSS 起步是教材模型;RFC 5681 规定初始窗口为 2~4 MSS,RFC 6928 提议扩到 10 MSS,Linux 2.6.39 起默认初始窗口就是 10 MSS。
“慢”是相对于一次性发全部窗口,实际增长是指数级。
2. 拥塞避免(Congestion Avoidance)#
cwnd >= ssthresh 后:每个 RTT → cwnd += 1 MSS(线性增长)
直到检测到丢包plaintext3. 快重传(Fast Retransmit)#
收到 3 个重复 ACK → 立即重传丢失的包(不等超时定时器)plaintext4. 快恢复(Fast Recovery)#
3 个重复 ACK 后:ssthresh = max(在途数据量/2, 2 MSS),cwnd = ssthresh + 3 MSS
(+3 是因为 3 个重复 ACK 说明已有 3 个包离开网络)
快恢复期间每再收到 1 个重复 ACK → cwnd += 1 MSS(窗口膨胀,维持发送)
收到确认新数据的 ACK → cwnd = ssthresh(窗口收缩)→ 进入拥塞避免
对比超时:ssthresh = max(在途数据量/2, 2 MSS), cwnd = 1 MSS
→ 回到慢启动plaintext(以上是 RFC 5681 的 Reno 规则;NewReno(RFC 6582)改进了一个窗口内多个丢包时的快恢复,Linux 实际还叠加了 SACK 和 PRR 等机制。)
区别: 3 重复 ACK → 网络还行只是丢了部分 → 减半。超时 → 可能严重拥塞 → 重置。
状态转换#
cwnd < ssthresh cwnd >= ssthresh
┌─────────┐ ┌──────────┐
│ 慢启动 │─────────────→│ 拥塞避免 │
│ 指数增长 │ │ 线性增长 │
└────┬────┘ └────┬─────┘
│ │
超时丢包 │ 3个重复ACK │
cwnd=1 │ cwnd=cwnd/2 │
回到慢启动 │ 快恢复→拥塞避免 │plaintext常见算法#
| 算法 | 特点 |
|---|---|
| Reno | 经典实现(加入快恢复) |
| Cubic | 基于三次函数增长,Linux 默认 |
| BBR | Google 推出,基于瓶颈带宽和最小 RTT 建模控速;v1(Linux 4.9 合入主线)基本不把丢包当拥塞信号,v2/v3 把丢包和 ECN 也纳入;主线内核至今仍是 v1,v3 需 Google 的树外补丁 |
面试回答(2分钟版)
TCP 拥塞控制的目标是防止发送方把网络打满,核心思想是 AIMD 即加性增乘性减。发送方维护一个拥塞窗口 cwnd,实际发送量取 cwnd 和接收方通告窗口 rwnd 的最小值。拥塞控制分四个阶段协同工作:慢启动阶段 cwnd 从 1 个 MSS 开始每收到一个 ACK 就加 1,效果是每个 RTT 翻倍呈指数增长,虽然叫”慢”但增长其实很快。当 cwnd 达到慢启动阈值 ssthresh 后进入拥塞避免阶段,改为每个 RTT 只加 1 个 MSS 做线性增长,试探网络容量。如果检测到丢包,处理策略取决于丢包信号:收到 3 个重复 ACK 触发快重传立即重传丢失的包,然后进入快恢复,ssthresh 减半、cwnd 设为 ssthresh 加 3,新数据被确认后 cwnd 回落到 ssthresh 再线性增长,因为 3 个重复 ACK 说明网络还能通只是丢了部分;如果是超时则认为网络严重拥塞,ssthresh 减半但 cwnd 直接重置为 1 回到慢启动。Linux 默认使用 Cubic 算法基于三次函数增长,Google 的 BBR 算法则以估算的瓶颈带宽和最小 RTT 为主来控制发送速率,不把丢包当作主要拥塞信号(v1 基本不看丢包,v2/v3 也会参考丢包和 ECN)。
追问与易错
追问方向:
- “慢启动为什么叫’慢’?”→ 相比一次发全部窗口,从 1 开始是”慢”的
- “拥塞控制和流量控制的区别?”→ 流量控制保护接收方(rwnd),拥塞控制保护网络(cwnd)
易错点:
- ❌ “慢启动增长很慢”——指数增长其实很快
- ❌ “丢包就回到慢启动”——3 重复 ACK 是快恢复(减半),超时才是慢启动(重置)