IT 论文精读 · PAPER 45
Van Jacobson & Michael Karels · SIGCOMM 1988
1988 年,Van Jacobson 给互联网的传输协议 TCP 打了一个补丁,让全网在流量暴涨时不会一起卡死。你今天每一次刷视频、下文件、开网页,背后都有它悄悄在替你「踩油门、踩刹车」——决定这一刻该发多快。没有它,互联网早在三十多年前就撑不下去了。
1986 年秋天,两台相距几百米、中间只隔三跳的机器之间,网速从每秒 3 万多比特暴跌到每秒 40 比特——慢了将近一千倍。没有人拔线、没有人攻击,就是大家一起拼命发,结果谁也发不动了。这很像高峰期的高速:车一多到某个点,不是慢一点,而是整条路彻底堵死、几乎不动。工程师给这个现象起了个名字:拥塞崩溃。
互联网上没有一个交通指挥中心告诉每台机器该发多快。Jacobson 的关键判断是:既然没人管,那就让每个发送方自己去「感觉」路堵不堵、然后自觉地收着点发。可网络又不会主动说「我堵了」——那发送方靠什么感觉?靠一个朴素的信号:丢包。在一条好线路上,包很少因为出错而丢,几乎全是因为某个路口排队排爆了、被丢掉。所以「我发的包没到」=「前面堵了」,这就是网络在跟你说话。
三个小动作,凑成一套自律:
① 按回音的节奏发。每发出一个包,对方收到会回一声「收到」(ACK)。Jacobson 让发送方只有听到一声回音、才放一个新包进网——就像往漏斗里倒水,只按它漏下去的速度倒,网络自然不会被灌爆。这声声回音,就成了替你打拍子的节拍器。
② 顺时慢加、堵时猛减。一切顺利时,每过一轮就把发送量悄悄加一点点(小心翼翼往上试探);一旦丢了包,立刻把发送量砍掉一半(急刹车)。慢慢加、狠狠减——正是这种「不对称」让所有人最终稳稳分到一份公平的带宽,而不是一起挤爆。
③ 起步先试探,别一上来就猛冲。刚开始不知道路有多宽,就从发一个包起步、每轮翻倍,直到第一次感到阻力再转成慢加——像进一条陌生的路先探探深浅,而不是一脚油门冲进去。
这套办法被装进当年的操作系统、成了 TCP 的标准动作,互联网从此再没发生过大范围拥塞崩溃,也才撑得起后来爆炸式的增长。直到今天,你手机上每一条连接,骨子里还在跑它的「慢加猛减」。诚实地说一句代价:它把所有丢包都当成「堵了」——可无线网里,包常常是被干扰弄丢的、路根本没堵,这时它也会白白地把速度减半,这是它在 Wi-Fi、4G 时代被诟病的老毛病。
没有中央调度,就让每个发送方按「对方的回音」打拍子发包、顺利时慢慢加速、一丢包就把速度砍半、起步先翻倍试探——靠这套人人自律的「慢加猛减」,互联网在没人指挥的情况下不再一起堵死。它是今天每一条网络连接的隐形司机。
想看拥塞崩溃曲线、自时钟原理、AIMD 与超时估计的机制? → 切到精读版
这篇论文诊断了 1986 年互联网首次拥塞崩溃(congestion collapse)的成因,并给 TCP 加上一套让端到端自我调速的算法——慢启动(slow-start)、拥塞避免(加性增、乘性减 AIMD)、更准的往返时间与超时估计——核心思想是把丢包当作「网络堵了」的信号,让每个发送方在没有中央调度的前提下自觉收放流量。这套算法进入 4.3BSD 后成为 TCP 的事实标准,是互联网得以规模化而不崩溃的关键地基。
作者 Van Jacobson(劳伦斯伯克利国家实验室 LBL)与 Michael Karels(UC Berkeley),发表于 SIGCOMM 1988。它上承 1970 年代的 TCP/IP 与「端到端论证」(把智能放在两端、网络保持简单);正面回应 1986 年起频发的拥塞崩溃;下启后来所有拥塞控制的谱系——Tahoe、Reno、NewReno,直到 CUBIC、BBR,都建在它奠定的框架上。
1986 年 10 月,Jacobson 观测到一件荒唐事:从 LBL 到伯克利校园、相距约几百米、中间仅三跳的链路,吞吐量从 32 Kbps 崩到 40 bps——掉了近三个数量级。没有硬件故障,纯粹是流量本身把网络逼死了。这就是拥塞崩溃。
崩溃的机理是一个正反馈的死亡螺旋:网络一堵,包在路由器队列里排队、RTT 变长;可当时的 TCP 用一个固定的超时公式(超时 ≈ 2 × 平滑RTT),在高负载下这个超时严重偏短,于是发送方把还在路上排队、并没真丢的包又重发了一遍;重复的包让本已拥堵的网络负载翻倍、更堵、RTT 更长、更多误判超时、更多重发……直到网络里跑的几乎全是无用的重复包,有效吞吐趋近于零。
更深的问题是:互联网没有中央调度,谁也不知道全局有多少流量、瓶颈在哪。所以控制只能是分布式、端到端的——每个连接自己观察、自己决定收放。难点在于:一群自私的发送方,靠各自的局部信息,怎么能自发收敛到「既不浪费带宽、又不把网络挤爆、还彼此公平」的状态?
Jacobson 的出发点是一条物理直觉——包守恒(conservation of packets):一条运行在「平衡态」的连接,应当做到网络里少出去一个包,才放一个新包进来,让在途的包总量稳定,正好填满而不溢出这条路。
怎么实现这种「一出一进」?答案优雅得近乎免费:用返回的 ACK 当时钟(self-clocking,自时钟)。每个 ACK 回来,说明有一个包已经离开网络、被对方收下,此时才允许注入一个新包。于是发送速率被自动锁定在瓶颈的处理速率上——瓶颈多久放行一个包,ACK 就多久回来一次,新包就多久发一个。你不需要知道瓶颈带宽是多少,网络自己会通过 ACK 的节奏「告诉」你。
自时钟只在「已经平衡」时成立,可连接刚建立时网络里一个包都还没有,ACK 时钟也就没启动。此时若按对方通告的大窗口一次性把一整窗数据全砸进去,瞬间就会冲爆瓶颈队列。慢启动的做法是:把新增的拥塞窗口 cwnd 从 1 个包起步,每收到一个 ACK 就把 cwnd 加 1。效果是窗口每过一个 RTT 翻一倍——1、2、4、8……名字叫「慢」,其实是指数增长,但相对「一上来就满窗」已是极温柔的试探。它一路加速,直到撞上第一次丢包或到达阈值,把 ACK 时钟平稳地「点着」。
试探到接近网络容量后,就不能再翻倍了,否则一步就冲过头。TCP 维护一个阈值 ssthresh:cwnd 低于阈值时用慢启动(指数涨);高于阈值后切换到拥塞避免——每个 RTT 只把窗口加 1(把 cwnd 每收到一个 ACK 增 1/cwnd),即加性增(additive increase),小步慢挪地贴着容量试探。
一旦检测到丢包(判定为拥塞),就乘性减(multiplicative decrease):把阈值砍半 ssthresh = cwnd/2,并把 cwnd 打回 1、重新慢启动爬升到新阈值再转加性增。为什么增是「加」、减是「乘」而不对称?因为拥塞一旦发生,队列是爆炸式堆积的,只有指数级(乘性)的猛减才压得住;而探测富余带宽必须保守,所以用最温和的加性增。这一「慢升-骤降」的锯齿,正是让众多连接自发收敛到公平且高效共享的关键——这背后有控制论上的依据(加性增乘性减能收敛到公平线)。
拥塞崩溃的导火索是误判超时导致的无谓重传,所以这篇同样重写了超时估计。旧 TCP 只跟踪平滑后的平均 RTT、用固定倍数 2 定超时;Jacobson 指出高负载下 RTT 的波动本身很大,必须把波动也估进来。新公式同时跟踪 RTT 的均值与平均偏差,取 超时 = 平滑RTT + 4 × 偏差,让超时随网络抖动自适应地放宽,从根上减少「把没丢的包当丢了」的误伤。再配合重传超时的指数退避(连续重传时把等待时间成倍拉长)与 Karn 算法(重传过的包不拿来估 RTT,避免二义性),才真正掐断了那条正反馈螺旋。
论文一共给 TCP 加了七个相互配合的新算法(上面的自时钟/慢启动、拥塞避免、RTT 方差估计、指数退避等)。效果直接而戏剧:在 Jacobson 团队的测试链路上,同样的硬件、同样的负载,加上这套算法后,一条严重拥塞、吞吐几乎归零的连接被重新拉回接近链路带宽的稳定吞吐,且多条连接能公平共存而不再互相拖垮。这些代码随 4.3BSD(Tahoe)发布、迅速被各操作系统采纳,成为全互联网 TCP 的默认行为。它没有华丽的定理,胜在可落地、立竿见影、且不需要改动网络中间设备——纯靠两端软件升级就治好了全网的病。
它奠定了互联网拥塞控制的整个范式:端到端、以丢包为信号、AIMD 收敛到公平。后来的 Reno / NewReno(加上快速重传、快速恢复,丢包时不必打回 1 而是减半后继续)、CUBIC(Linux 默认,为高带宽长距离链路重设增长曲线)乃至 Google 的 BBR,全都是在它的框架上迭代或与之对话。更深远的是它示范了一种思想:在没有中央权威的大规模系统里,靠一致的、自私但自律的局部规则,也能涌现出全局的稳定与公平——这条「TCP 友好(TCP-friendly)」的社会契约,是互联网能长成今天这样而不塌的隐形宪法。
① 一句话:给 TCP 加一套端到端自我调速算法,把丢包当拥塞信号,让没有中央调度的互联网不再一起崩溃。
② 痛点:1986 年拥塞崩溃,吞吐从 32 Kbps 崩到 40 bps;祸首是误判超时→无谓重传→更堵的正反馈死亡螺旋。
③ 包守恒 + 自时钟:以返回的 ACK 为拍子,一出一进地放包,速率自动锁定瓶颈处理速率,无需知道带宽。
④ 慢启动:cwnd 从 1 起步、每 RTT 翻倍,温和地点着 ACK 时钟、进入平衡态。
⑤ 拥塞避免 AIMD:过阈值后每 RTT 只 +1(加性增),丢包则阈值减半(乘性减);慢升骤降的锯齿收敛到公平又高效。
⑥ 拆引信:用 RTT 均值+偏差估超时(SRTT + 4×偏差)+指数退避+Karn 算法,掐断误判重传的螺旋。
⑦ 影响:随 4.3BSD 落地成 TCP 标准,互联网从此不再拥塞崩溃;Reno/CUBIC/BBR 皆其后裔,确立端到端拥塞控制范式。
⑧ 局限:丢包≠一定拥塞(无线吃亏)、缓冲区膨胀、RTT 不公平、难填高带宽长时延管道、依赖人人守规矩。