为什么下载不能立刻到达最快速度——从一个现象看拥塞控制算法
下载速度逐步提升源于TCP拥塞控制算法的慢启动机制,通过试探网络承载能力避免拥塞。改进算法如CUBIC和BBR进一步优化了传输效率和稳定性。 2025-9-13 11:23:47 Author: sspai.com(查看原文) 阅读量:5 收藏

如果你经常下载大文件、游戏,可能会发现下载在开始时并不能立即占满网络带宽,而是从较低速度逐步提升,最终才达到稳定的传输速率。为什么下载的时候总不能在第一时间到达最快速度呢?你可能觉得这得是下载策略的问 ...

如果你经常下载大文件、游戏,可能会发现下载在开始时并不能立即占满网络带宽,而是从较低速度逐步提升,最终才达到稳定的传输速率。

为什么下载的时候总不能在第一时间到达最快速度呢?

你可能觉得这得是下载策略的问题,但这实际上是系统在刻意「试探」网络的承载能力,在这篇文章里我们将一起探索这个小细节背后的故事。

为什么要「试探」网络的承载能力?

不少人或许会认为,即使不进行「试探」,设备只需按预设速度传输即可。预设速度偏低,最多只是传输变慢;预设速度偏高,也会在触碰实际瓶颈后被限制到最大可用速度。

不过已经有人帮我们实践过了,早在上个世纪 80 年代,早期互联网就这样「处理」的,而最后的结果就是出现了网络拥塞崩溃的现象。不过我们这里会举个例子帮助大家理解,所有设备如果都用最大速度去访问互联网资源的话,就像在城市早高峰的主干道上,突然所有车主都一脚油门提了速。这时:

  • 路由器队列被短时间内大量 TCP 流量填满:车流瞬间塞满道路(相当于路由器队列),车与车之间没有缓冲余地;
  • 数据包大规模丢失,触发了客户端的重传风暴:车子挤成一团,频繁刹车和追尾(对应数据包丢失与重传风暴),反而让道路更加瘫痪;
  • 骨干网络的有效吞吐量下降到一个很低的数字:本来能高效通行的车道(网络带宽),因为混乱和事故,实际能通过的车子越来越少;
  • 网络几乎不可访问:最后结果就是「寸步难行」,没有车能通过。

所以,最终诞生了 TCP 拥塞控制算法,就像引入了一套交通管制规则。形成了一套完整机制,包括慢启动(Slow Start)、拥塞避免(Congestion Avoidance)、快速重传(Fast Retransmit)和快速恢复(Fast Recovery),用以解决上述问题。而文章开头提到的「下载在开始时并不能立即占满网络带宽」,正是慢启动机制的体现。

当网络链路带宽被完全占用时,路由器或交换机的缓存队列会迅速堆满。为避免无限积压导致延迟失控,大多数网络设备会采用主动作废策略:当队列达到预设阈值时,直接丢弃新到的数据包。这些丢包信号会被 TCP 发送端解读为网络已到达极限。

这个过程就像一条高速公路接近极限承载时,收费站(相当于缓存队列)会发现,高速公路上的车很快就没办法保持安全距离了。所以为了避免车辆出现追尾的事故,收费站通常会采取限流措施:当安全距离过短时,会直接拦下新车,不允许进入。拦下的这个动作对应网络设备的「主动丢包」策略,车距则对应了「丢包」信号。

在慢启动阶段,连接速率不断上升,一旦接近链路上限,拥塞控制算法便会切换到拥塞避免阶段,以更平缓的方式增加发送速度。慢启动好比车辆刚驶上高速时,起初加速迅猛,但当发现前方车流逐渐密集,就会转入拥塞避免阶段——车速提升变得更谨慎,保持车距以免追尾其他车辆。

如果这时候出现零星丢包,发送端会通过快速重传等机制略微收紧发送窗口;若丢包持续且比例偏高,TCP 会判定发生拥塞,触发拥塞避免,甚至回到慢启动阶段,大幅降低发送速率。这样,发送端与网络之间形成了「试探—反馈—调整」的闭环,既尽量利用带宽,又防止网络崩溃。

以之前的例子继续距离,也就是只是偶尔看到自己和前后车的车距近了(零星丢包),司机会稍微松点油门(快速重传,轻微收紧速度)。但如果看到所有车道跟车都跟得很近(丢包比例高),司机就会认为有车祸的风险,于是猛踩刹车,保持车距(回到慢启动阶段,大幅降速)。

这样,任何设备既不精确测量各条链路的可用带宽,也不尝试对网络全局优化,而是依靠丢包这一「试探—反馈—调整」策略来驱动调节。这种低成本、分布式、无需额外协商的机制,在当时乃至今日的互联网依然行之有效。整个过程就像在高速上的司机,虽然每一辆车都不会实时知道这条高速公路上的车流量、也不会和其他所有司机开会协调「谁先走谁后走」,只需要看一眼车距(丢包信号),就能不断调整自己的车速和跟车距离。

提升网络性能的不同思路

虽然这套机制自诞生起就表现得稳定可靠,但随着互联网环境愈加复杂,仅依靠丢包来判断网络拥堵开始暴露出问题。「等丢包再反应」就像在高速公路上单纯依赖追尾事故来感知车流密度。如果车流过多,等到追尾(丢包)发生时,虽然能提醒司机减速,但代价不小:依旧会发生车辆受损(应用层性能下降)、车道受阻(队列重传带来的额外带宽消耗)等问题。

而且有的时候丢包并不是网络阻塞的信号。比如,线路质量差、无线信号衰减、硬件故障,甚至是防火墙或策略丢弃,都会出现丢包的情况。这类丢包并不意味着网络已经「挤满」,却会误导拥塞控制算法,以为必须收紧发送速率,从而造成实际吞吐量被不必要地压低。

这便引出了新的思路:能否在「追尾」发生之前,就提前感知前方车流的紧张程度?就像在高速上设置电子限速屏或每辆汽车里都追尾提醒,让司机无需看到事故才减速,而是能够更平滑地调整车速。同样地,在网络领域,人们尝试借助更智能的拥塞控制算法与全新的拥塞通知机制来提升性能。

改进拥塞控制算法

第一个方案是改进拥塞控制算法。现有算法在反应速度上稍显迟缓,我们可以考虑引入更智能的机制,从更多蛛丝马迹中捕捉到潜在的拥堵信号,从而提前规避问题。这个逻辑其实很好理解,就像现在汽车上的辅助驾驶系统一样,也是依靠多种信号综合判断。目前比较为人所知的三种拥堵算法分别是 Reno、CUBIC 和 BBR,下面我们分别来看看他们之间的区别。

Reno 属于早期的拥塞控制算法(更早的是 Tahoe,相比之下缺少快速恢复机制)。它将丢包视为拥塞信号,一旦检测到丢包便立即降速并重传,逻辑简单且兼容性好。

如果继续用之前的例子来打比方的话,Reno 就像一位较为保守的自动化算法:行驶中会不断加速,直到前方真的发生追尾(丢包)才猛然把车速降到一半,然后再缓慢地一点点提速。但 Reno 这样的这种算法很容易在高速上制造「走走停停」的局面:车速刚提起来不久,就因为要追尾(丢包)而猛踩急刹,结果导致道路利用率不高,车流也显得不够平稳。

CUBIC 和 Reno 的性能对比

CUBIC 就是 Reno 的一个迭代,在拥堵避免阶段换用了三次曲线 CUBIC,是目前 Windows、Linux 和 macOS 的默认拥塞控制算法,而且从 2024 年开始也正式成为 IETF 标准(RFC 9438)。什么是三次曲线呢?直接举例子来说,CUBIC 有「记忆」,他会记得上次要追尾之前的最高安全速度,然后先接近这个速度,再慢慢变快一点的,看看是不是能更快。所以 CUBIC 能在更大的带宽上更快地找到合适的速度,比 Reno 相比不会频繁掉速,更能合理利用资源。

比如在 macOS 自 Yosemite 起默认采用 CUBIC 算法,还可以用 nettop -m tcp 看到 macOS 目前发起的所有链接

除了目前广泛使用的 Reno 和 CUBIC,还有一些拥塞控制算法也比较流行。首先是 Google 2016 年开发的 BBR 算法,目前正在开发 v3 版本。它不同于我们之前介绍的、依赖丢包信号的算法,它换用了一个新的思路:通过实时估计网络的瓶颈带宽和最小往返时延(RTT),来决定发送速率。

BBR 通过持续测量链路中的可用带宽,力求逼近瓶颈处的最高承载能力;同时,以最小 RTT 作为无拥塞状态下的参考基准,防止因队列过度堆积而导致时延膨胀。整体来看,BBR 不依赖丢包信号来触发收敛,而是基于带宽与时延的模型动态调整发送速度,使实际速率趋近于「带宽 × 最小 RTT」,从而在充分利用带宽的同时有效控制时延。

我们继续以之前的例子打比方,BBR 更聪明,它不会一味猛踩油门等到真的撞车(丢包)才刹车,而是会随时观察道路的最大通行速度(瓶颈带宽),并记住在不堵车时从家到公司的最短通勤时间(最小 RTT)。如果预估时间已经超过了最短通勤时间,BBR 就会主动控制控制速度来减少路面拥堵;当预估时间重新回到最短通勤时间,BBR 又会主动回到最快速度。

所以与 Reno、CUBIC 那种「撞一下才懂收敛」的风格不同,BBR 依靠的是对带宽和时延的持续跟踪,动态调节车速,使整个路面上的车流更加平稳。不仅能最大化道路利用率,还能减少「走走停停」式的大拥堵。不过,BBR 也有着自己的问题,它在某些场景下会与传统拥塞控制(比如之前的 Reno/CUBIC)竞争时表现出「不够公平」,因此也出现了后续的 v2/v3 改进版本。

在现在,BBR 已经进入 Linux 主线,而 Windows 更是在 Windows 11 22H2 版本以后升级到了 BBRv2 版本。如果你一定想试试这个新的 BBR 算法的话可以试试下面这套命令:


文章来源: https://sspai.com/prime/story/download-speed-and-congestion-control-algo
如有侵权请联系:admin#unsafe.sh