1986 年 10 月互联网真的崩过一次:伯克利到劳伦斯实验室直线 400 米,吞吐从 32 kbps 掉到 40 bps。下面这两个开关就是 Jacobson 1988 年那篇论文加进去的两样东西——而它们管的不是同一件事:一个管「这条链路还能不能用」,一个管「你还能不能分到你那一份」。
动手前我写下三条预期,两条是错的。① 我以为「关掉 AIMD 吞吐会塌一个数量级」——实测吞吐还是 100%,塌的是公平性(0.997 → 0.461)。③ 我以为「两个开关凑在一起才要命」——它们各管各的,互不重叠。
真正塌吞吐的是重传定时器:只关它,吞吐 100% → 6.2%(塌 16 倍)。因为固定 200 ms 的 RTO 比实际 RTT 短得多,发送方在 ACK 还没回来时就重发——链路搬的全是同一个包的副本。这正是 1984 年 Nagle 给「拥塞崩溃」下的定义。
关掉它,每个应用自己拍一个窗口(有的开 8,有的开 512)。链路照样满载、吞吐照样 100%,可公平性从 0.997 掉到 0.461——窗口开得大的把别人挤没了。
更狠的是那个「放一条不守规矩的流」按钮:49 条守规矩、1 条窗口顶死 512,公平性掉到 0.184,而总吞吐一点没变。它没有伤害网络,它只是把别人的份拿走了。AIMD 是一份社会契约,不是一条物理定律。
把缓冲区滑块拉大:AIMD 开着时排队时延从 200 ms 一路涨到 1906 ms。因为 AIMD 只在丢包之后才退让,而丢包只在缓冲区装满之后才发生——缓冲区有多大,队列就排多长。
这就是 bufferbloat,也是 CoDel、BBR 这些后来的东西存在的理由。⚠ 同一根滑块还能看到另一件事:缓冲区越大,关掉之后塌得越狠(B=200 时只差 2.0 倍,B=6000 时差 31.0 倍)。
① 把流数拖到 1:两边完全一样,吞吐都是 100%、公平性都是 1.000(这一格我第一版做错过:那条流拿到的窗口是区间最低端,连链路都占不满)。拥塞控制解决的是「多个人共享」,一个人的时候它一分钱不值。
② 这里只有一个瓶颈。真实的多跳网络还有另一条崩溃路径——包在第一跳吃掉了带宽,却在第二跳被丢掉,那份带宽彻底白费。单瓶颈模型看不见它,所以这里量到的是 16 倍,而 1986 年那个 1000 倍是史实,不是这个模型的输出。