拥塞控制(Congestion Control)是计算机网络(尤其是 TCP/IP 体系)中的核心机制,用来防止过多数据同时注入网络,导致路由器/链路过载、丢包激增、吞吐量崩溃。它和“流量控制(Flow Control)”不同:流量控制是端到端防接收方来不及处理,拥塞控制是全局防网络本身扛不住。
一、为什么需要拥塞控制
- 网络资源(带宽、缓存、CPU)有限
- 发送方盲目提速 → 路由器队列满 → 丢包 → 重传 → 更堵(正反馈崩溃)
- 目标:在公平前提下,尽量跑满可用带宽,同时避免抖动和丢包风暴
二、TCP 拥塞控制经典框架(4 个阶段)
目前互联网主流是 TCP Reno / CUBIC(Linux 默认),逻辑上分四块:
1. 慢启动(Slow Start)
- 初始拥塞窗口
cwnd = 1~10 MSS - 每收到一个 ACK,
cwnd += 1 MSS(指数增长) - 直到达到 慢启动阈值 ssthresh 转入拥塞避免
2. 拥塞避免(Congestion Avoidance)
cwnd线性增长(每个 RTT 加 1 MSS)- 试探网络容量,避免一下子冲垮网络
3. 拥塞发生时的反应
| 信号 | 算法(Reno) | 说明 |
|---|---|---|
| 超时重传 | ssthresh = cwnd/2,cwnd=1,重新慢启动 |
认为网络很严重 |
| 收到 3 个重复 ACK | 快重传 + 快恢复:ssthresh=cwnd/2,cwnd=ssthresh+3 |
认为只是偶发丢包 |
4. 快恢复(Fast Recovery)
- 在 3-ACK 场景下不回到慢启动,避免吞吐断崖
- 收到新 ACK 后进入拥塞避免
现代 Linux 用 CUBIC:把 cwnd 作为时间的立方函数,在高 BDP(带宽×延迟)网络下比 Reno 更激进、收敛更快。
三、其他重要拥塞控制思路
- TCP BBR(Google):不依赖丢包判断拥塞,而是建模“瓶颈带宽 + RTT”,主动把发送速率控制在 BtlBw 附近,抗丢包、低延迟,适合长肥管道和视频/QUIC
- AQM 队列管理:路由器侧 RED、CoDel、PIE,提前丢包或标记 ECN,让端系统早减速
- ECN(显式拥塞通知):路由器在 IP 头打 CE 标记,接收方回显给发送方,不必等丢包
- QUIC:基于 UDP,但自带类 BBR 拥塞控制,连接迁移、多路复用不互相阻塞
四、和流量控制的区别(常考)
- 流量控制:滑动窗口,
rwnd,怕接收方缓冲区爆 - 拥塞控制:
cwnd,怕网络中间设备爆 - 实际发送窗口 =
min(cwnd, rwnd)
五、一句话总结
拥塞控制就是:发送方通过丢包/延迟/ECN 等信号,动态调整 cwnd,在“不敢发”和“发不够”之间找平衡点;现代趋势是从“丢包即拥塞”走向“测量瓶颈带宽”的模型化控制(BBR)。