Stanford CS144 学习笔记 (四):网络拥塞控制与 AIMD 算法
导语:在上一单元中,我们学习了“流量控制 (Flow Control)”,它解决的是接收方处理不过来的问题。但在真实的互联网中,如果所有人都全速发包,中间的路由器处理不过来怎么办?这就会导致灾难性的“网络崩溃”。本单元,我们将探究 TCP 是如何凭借天才般的“拥塞控制 (Congestion Control)”机制,拯救互联网于水火之中的。

1. Congestion - Basic Ideas (网络拥塞的本质)
控制拥塞的核心目的,是防止整个网络因为过载而陷入崩溃。
1.1 So, what is it? (什么是拥塞?)
拥塞产生的原因非常简单:需求 > 容量。
具体表现在不同的时间尺度上:
- 微观 (Microscopic):两个数据包在路由器端口同时碰撞。
- 中观 (Macroscopic):多条数据流 (Flows) 瞬间耗尽了某条链路的物理带宽。
- 宏观 (Systemic):晚高峰期间,海量用户同时挤入网络(类似春运的高速公路)。
恶性正反馈:当路由器发生拥塞开始丢包时,如果不加控制,发送方会因为超时而重传更多的数据包,导致原本就拥堵的网络雪上加霜,最终吞吐量降为零,这就是“网络崩溃 (Congestion Collapse)”。
1.2 Congestion is unavoidable (拥塞是不可避免的)
- 为什么不把路由器的 Buffer 做得无限大?
如果 Buffer 极大,确实不会丢包了,但数据包会在里面排队等上好几秒(Bufferbloat,缓冲区膨胀),导致端到端延迟高得离谱。这对网络利用率和实时应用来说是一场灾难。 - 丢包是好事还是坏事?
无意义的丢包是对上游网络资源的浪费;但适度的丢包,其实是网络在向终端发出“我快撑不住了”的警告信号。
1.3 Fairness and Throughput (公平与吞吐量的博弈)
网络设计者面临一个两难境地:是追求绝对的总吞吐量最大化,还是追求每个用户的绝对公平?
- Max-min Fairness (最大最小公平性):这是互联网普遍认可的公平原则。核心思想是“劫富济贫”——在分配资源时,优先满足需求最小(最吃亏)的流,如果还有剩余,再平均分配给需求更大的流。坚决避免少数霸道流量挤占所有资源。
2. Congestion - Basic Approaches (应对拥塞的基础策略)
如何把网络拥塞的情况告诉发送方?有两种截然不同的流派:
2.1 Network-based (基于网络核心的策略)
让网络中间的路由器主动发声。
- 机制:当路由器快满时,主动向终端发送 Signal(信号),告知正在拥堵。
- ECN (Explicit Congestion Notification, 显式拥塞通知):路由器会在处理数据包时,在 IP 头部打上拥塞标记。这个标记到达目标主机后,目标主机会借助返回的 ACK 报文“搭便车”,把拥塞警告带回给源主机。
2.2 End-host based (基于终端主机的策略)
路由器什么都不用管,全靠网络边缘的终端主机自己去猜!
- TCP Congestion Control:TCP 采用的就是这种策略。它把网络当成一个黑盒。
- 探测机制:通过维护一个名为拥塞窗口 (Congestion Window, cwnd) 的变量,结合滑动窗口策略,利用 RTT (往返时间) 和是否丢包,来动态推测网络的拥堵程度。
2.3 AIMD (加性增,乘性减)
TCP 拥塞控制的核心算法。这是一种“慢慢增加,快速减少”的试探策略。
- Additive Increase (加性增加):如果没有发生拥塞,发送速度“一点一点”地缓慢增加。
- Multiplicative Decrease (乘性减少):一旦检测到拥塞(丢包),发送速度“断崖式”砍半。
- 视觉表现:这导致 TCP 的发送窗口在时间轴上呈现出经典的 “Sawtooth” (锯齿波) 形状。
3 & 4. Congestion - AIMD 动态表现
TCP 不会刻意避免丢包,相反,“丢包”正是 AIMD 用来寻找网络容量上限的探测雷达。
数学逻辑 (Single & Multiple flows)
- 收到 ACK 时 (if received):
W <- W + 1/W。
(注:意味着每收到一个确认,窗口增加1/W,当收到一整窗W个确认时,窗口刚好增加1。这保证了每经过一个 RTT,窗口大小线性 +1) - 发生丢包时 (if dropped):
W <- W / 2。
(注:立刻将窗口砍半,给网络极大的喘息空间)
吞吐量公式
在 AIMD 算法下,一条流的长期平均吞吐量近似为:Throughput ∝ W / RTT。
在多条流共享链路时,AIMD 的这种锯齿状调整,最终会在数学上奇迹般地收敛到一条代表“绝对公平”的均衡线上。
5. TCP Congestion Control Ⅰ (TCP 拥塞控制演进史)
TCP 内部维护了几个关键变量来控制速度:cwnd (拥塞窗口) 和 ssthresh (慢启动阈值)。
5.1 TCP Three Questions (TCP 的哲学三问)
设计任何可靠协议都要回答:
- 什么时候发送新数据? (由 cwnd 和滑动窗口决定)
- 什么时候重传数据? (由超时或三次重复 ACK 决定)
- 什么时候确认数据? (累计确认机制)
5.2 状态流转 (State Transitions)
TCP 在运行中主要在以下状态中切换:
- Slow Start (慢启动):
- 名字叫“慢”,其实是指数爆炸!
- 初始窗口很小(如 1 个包),但每收到一个 ACK,窗口加 1。这意味着每个 RTT 窗口翻倍 (1→2→4→81 \to 2 \to 4 \to 81→2→4→8)。
- 目的:以极快的速度探测出当前网络的可用容量,直到触碰阈值 (ssthresh)。
- Congestion Avoidance (拥塞避免):
- 当
cwnd >= ssthresh时,进入此阶段。 - 退化为 AIMD 的线性增长模式,每个 RTT 窗口仅仅加 1,谨慎试探拥塞点。
- 当
6. TCP Congestion Control Ⅱ (超时与时钟机制)
6.1 RTT Estimation (RTT 估计与超时陷阱)
- 为什么难? 现实网络中 RTT 的波动极大。如果超时时间设得太长,丢包后系统迟迟不重传,浪费时间;设得太短,又会导致把正常延迟误判为丢包,引发频繁的无效重传(加剧拥堵)。
- Self-Clocking (自时钟机制):TCP 巧妙地利用接收方返回的 ACK 作为系统运转的“心脏起搏器”。收到一个 ACK,就代表网络腾出了一个包的空间,发送方就可以安全地注入一个新包。
6.2 Pre-Tahoe 到 Tahoe 的飞跃
- 早期 TCP (Pre-Tahoe):完全依赖定时器超时。只要超时,就把窗口重置为 1,效率极其低下。
- TCP Tahoe 的两大创举:
- Fast Retransmit (快速重传):如果发送方连续收到 3 个重复的 ACK,说明后续的包到了,但中间某个包丢了。此时不等超时,立刻重传丢失的包!
- 但是,Tahoe 依然比较原始:无论是超时还是 3 次重复 ACK,它都会把
ssthresh设为当前窗口的一半,然后极其保守地把cwnd降为 1,重新开始慢启动。
7. TCP Congestion Control Ⅲ (Reno 与 NewReno)
为了解决 Tahoe 每次丢包都要从 1 重新开始的低效问题,专家们对 TCP 进行了迭代。
7.1 TCP Reno (引入快速恢复)
- 核心改进:丢包后不再傻傻地回到 0 点!
- Fast Recovery (快速恢复):如果是超时丢包,Reno 和 Tahoe 一样回到 1。但如果是收到 3 个重复 ACK 触发的丢包,Reno 认为“既然还能收到 ACK,说明网络还有流通能力”。
- 此时,Reno 直接把
cwnd减半,跳过慢启动,直接从半山腰进入拥塞避免阶段。极大提高了网络吞吐量。
7.2 TCP NewReno (终极优化)
- Reno 的致命弱点:如果一个发送窗口内有多个包同时丢失,Reno 的快速恢复机制会彻底混乱,导致多次将窗口减半,最终饿死自己。
- NewReno 的优化:优化了快速恢复机制的逻辑,引入了“部分确认 (Partial ACK)”的概念。它能够敏锐地识别出一个窗口内的多次丢包,并在一次恢复周期内高效处理,避免了盲目减半。
7.3 对比总结表
| 版本 | 关键改进 | 收到 3 个重复 ACK 的反应 | 效率评价 |
|---|---|---|---|
| Tahoe | 引入快速重传 | cwnd = 1,重新慢启动 |
丢包后恢复极慢 |
| Reno | 引入快速恢复 | cwnd = cwnd / 2,拥塞避免 |
恢复快,但怕单窗多丢包 |
| NewReno | 优化多重丢包 | cwnd = cwnd / 2,智能恢复 |
更复杂,更高效 |
8. TCP Congestion Control Ⅳ (拥塞控制的终极目标)
回顾 AIMD,它实际上在两者之间实现了完美的平衡:
- Service Provider (运营商/网络层):希望
Maximize link utilization(链路利用率最大化,别让线路空着)。 - User (终端用户):希望
Fair share(公平共享,谁也别独占带宽)。
通过分布式的 AIMD 探测,TCP 成功避免了 Congestion Collapse,支撑起了今天庞大而繁荣的互联网。
9. Reading an RFC (阅读互联网的“宪法”)
RFC (Request for Comments) 是 IETF 发布的技术规范文档。互联网上所有的规则,都在这里面。
- History:从 1969 年开始发布,记录了互联网从无到有的史诗。
- Necessities (为什么要读?):
- 写底层代码(如开发服务器、抓包工具)时的最高权威参考。
- 网络工程师排查疑难杂症的终极词典。
- Something Common (经典 RFC 必知):
- TCP 协议:
RFC 793 - HTTP 协议:
RFC 7230 - DNS 协议:
RFC 1035
(注:阅读 RFC 不需要从头读到尾,学会利用目录,找到你需要的 Protocol Header 结构和状态机定义即可。)
- TCP 协议:
更多推荐


所有评论(0)