诞生于1974年的TCP协议(Transmission Control Protocol,传输控制协议)绝对算得上是最古老的网络协议之一,很可能是当今互联网上使用最多的网络协议。我们每个人每天不经意间就会发送和接收几十万甚至超过一百万以上的TCP数据包用来收看视频、玩游戏或者进行网络社交。
再进一步,也许你还了解目前互联网上最流行的两种传输协议UDP和TCP。UDP概括起来是一个“发送后不管”的协议。它是无状态的,没有拥塞控制或可靠的传输支持,这也导致了网络运营商会针对UDP协议的限流。我们经常看到UDP被用于DNS(域名系统)和NTP(网络时间协议)等。与之相对,TCP则像是UDP互补的孪生兄弟,提供了可靠的传输和流量控制,因此TCP协议也变得相当复杂。
人们通常认为TCP和UDP的主要区别就是TCP给我们提供了可靠的数据包传输。当然这是TCP最重要的功能之一,但TCP协议还为我们提供了流量控制。流量控制关乎网络使用的公平性,这对互联网的有效运行是至关重要的。TCP使用多种拥塞控制策略来避免拥塞。具体来讲,TCP会为每条连接维护一个“拥塞窗口”来限制可能在端对端间传输的未确认分组的总数量。并且,TCP在一个连接初始化或超时后使用一种“慢启动”机制来增加拥塞窗口的大小。所谓的“慢启动”,指的是初始值虽然比较低,但其增长极快:当每个分段得到确认时,拥塞窗口会增加一个MSS(Maximum segment size),使得在每次往返时间(Round-trip time,RTT)内拥塞窗口能高效地双倍增长。设想一下,如果没有这种形式的流量控制,互联网注定会在海量的数据传输之下不堪使用。
许多年来,不同的流量控制算法已经在各种TCP堆栈中实现和使用。你可能听说过TCP上的一些术语,例如Cubic、Tahoe、Vegas、Reno、Westwood,以及最近流行的BBR等。这些都是TCP中使用的不同拥塞控制算法。这些算法的作用是决定发送方应该以多快的速度发送数据,并同时适应网络的变化。如果没有这些算法,我们的互联网一定会被数据填满并且崩溃。
在Linux 下检查当前可用的拥塞算法可以使用如下命令:
sysctl net.ipv4.tcp_available_congestion_control
在我的这台机器上就得到了如下的结果 :
net.ipv4.tcp_available_congestion_control = reno cubic bbr bbr2 hybla highspeed htcp veno westwood vegas
如果想了解当前使用了哪一种拥塞算法可以使用以下命令:
sysctl net.ipv4.tcp_congestion_control
得到的结果如下。可以看出当前使用的是Cubic算法
net.ipv4.tcp_congestion_control = cubic
这里提到的Cubic 是一种较为温和的拥塞算法,它使用三次函数作为其拥塞窗口的算法,并且使用函数拐点作为拥塞窗口的设置值。Linux内核在2.6.19后使用该算法作为默认TCP拥塞算法。我们今天所使用的绝大多数Linux 分发版本,例如Ubuntu、Amazon Linux 等均将Cubic作为缺省的 TCP流量控制的拥塞算法。
BBR 算法
TCP的BBR(Bottleneck Bandwidth and Round-trip propagation time,BBR)是谷歌在2016年开发的一种新型的TCP 拥塞控制算法。在此以前,互联网主要使用基于丢包的拥塞控制策略,只依靠丢失数据包的迹象作为减缓发送速率的信号。这样做的的效果还是不错的,但随着全球化互联网的迅速普及&