再谈 TCP 拥塞控制!
扫描二维码
随时随地手机看文章
1.拥塞控制简史
来看下维基百科对TCP/IP协议栈的一些介绍,笔者做了少量的修改来确保语句通顺:
互联网协议套件是一个网络通信模型以及整个网络传输协议家族,由于该协议簇包含两个核心协议:TCP(传输控制协议)和IP(网际协议),因此常被通称为TCP/IP协议族。
TCP/IP协议对于数据应该如何封装、定址、传输、路由以及在目的地如何接收等基本过程都加以标准化。它将通信过程抽象化为四个层次,并采取协议堆栈的方式分别实现出不同通信协议,实际使用的四层结构是七层OSI模型的简化。我们可以看到TCP/IP协议栈是一个简化的分层模型,是互联网世界连接一切的基石,一起来看一张七层模型vs四层模型的简图:
范·雅各布森Van Jacobson是目前作为互联网技术基础的TCP/IP协议栈的主要起草者,他以其在网络性能的提升和优化的开创性成就而闻名。2006年8月,他加入了帕洛阿尔托研究中心担任研究员,并在位于相邻的施乐建筑群的Packet Design公司担任首席科学家。在此之前,他曾是思科系统公司首席科学家,并在位于劳伦斯伯克利国家实验室的网络研究小组任领导者。
范·雅各布森因为在提高IP网络性能提升和优化所作的工作而为人们所知,1988到1989年间,他重新设计了TCP/IP的流控制算法(Jacobson算法),他因设计了RFC 1144中的TCP/IP头压缩协议即范·雅各布森TCP/IP头压缩协议而广为人知。此外他也曾与他人合作设计了一些被广泛使用的网络诊断工具,如traceroute,pathchar以及tcpdump 。如图为Van Jacobson计算机名人堂的简介:范·雅各布森于2012年4月入选第一批计算机名人堂,计算机名人堂简介:https://www.internethalloffame.org/inductees/van-jacobson
https://ee.lbl.gov/papers/congavoid.pdf我们常用的tracetoute和tcpdump也是van-jacobson大神的杰作,作为互联网时代的受益者不由得对这些互联网发展早期做出巨大贡献的开拓者、创新者、变革者心生赞叹和敬意。
2.流量控制和拥塞控制
TCP是一种面向连接的、可靠的、全双工传输协议,前辈们写了很多复杂的算法为其保驾护航,其中有一组像海尔兄弟一样的算法:流量控制和拥塞控制,这也是我们今天的主角。
2.1 流量控制简介
流量控制和拥塞控制从汉语字面上并不能很好的区分,本质上这一对算法既有区别也有联系。
In data communications, flow control is the process of managing the rate of data transmission between two nodes to prevent a fast sender from overwhelming a slow receiver.
It provides a mechanism for the receiver to control the transmission speed, so that the receiving node is not overwhelmed with data from transmitting node.翻译一下:
在数据通信中,流量控制是管理两个节点之间数据传输速率的过程,以防止快速发送方压倒慢速接收方。
它为接收机提供了一种控制传输速度的机制,这样接收节点就不会被来自发送节点的数据淹没。可以看到流量控制是通信双方之间约定数据量的一种机制,具体来说是借助于TCP协议的确认ACK机制和窗口协议来完成的。
图中RcvBuffer是接收区总大小,buffered data是当前已经占用的数据,而free buffer space是当前剩余的空间,rwnd的就是free buffer space区域的字节数。
HostB把当前的rwnd值放入报文头部的接收窗口receive window字段中,以此通知HostA自己还有多少可用空间, 而HostA则将未确认的数据量控制在rwnd值的范围内,从而避免HostB的接收缓存溢出。可见流量控制是端到端微观层面的数据策略,双方在数据通信的过程中并不关心链路带宽情况,只关心通信双方的接收发送缓冲区的空间大小,可以说是个速率流量匹配策略。
2.2 拥塞控制的必要性
前面我们提到了微观层面点到点的流量控制,但是我们不由地思考一个问题:只有流量控制够吗?答案是否定的。
-
如何感知拥塞
-
如何利用带宽
-
拥塞时如何调整
3.理解拥塞控制
看到一篇文章说到TCP 传输层拥塞控制算法并不是简单的计算机网络的概念,也属于控制论范畴,感觉这个观点很道理。
http://www.cs.cmu.edu/~srini/15-744/F02/readings/BP95.pdf文档对Vegas算法和New Reno做了一些对比,我们从直观图形上可以看到Vegas算法更加平滑,相反New Reno则表现除了较大的波动呈锯齿状,如图所示:
3.1 拥塞窗口cwnd
从流量控制可以知道接收方在header中给出了rwnd接收窗口大小,发送方不能自顾自地按照接收方的rwnd限制来发送数据,因为网络链路是复用的,需要考虑当前链路情况来确定数据量,这也是我们要提的另外一个变量cwnd,笔者找了一个关于rwnd和cwnd的英文解释:
Congestion Window (cwnd) is a TCP state variable that limits the amount of data the TCP can send into the network before receiving an ACK.
The Receiver Window (rwnd) is a variable that advertises the amount of data that the destination side can receive.
Together, the two variables are used to regulate data flow in TCP connections, minimize congestion, and improve network performance.笔者在rfc5681文档中也看到cwnd的定义:
3.2 拥塞控制基本策略
拥塞控制是一个动态的过程,它既要提高带宽利用率发送尽量多的数据又要避免网络拥堵丢包RTT增大等问题,基于这种高要求并不是单一策略可以搞定的,因此TCP的拥塞控制策略实际上是分阶段分策略的综合过程:
3.3 TCP拥塞控制算法常见版本
实际上TCP算法有很多版本,每个版本存在一些差异,在这里简单看一下维基百科的介绍:
-
算法命名规则
TCP 算法名的命名方式最早出现在Kevin Fall和Sally Floyd1996年发布的论文中。
-
TCP Tahoe 和TCP Reno
这两个算法代号取自太浩湖Lake Tahoe和里诺市,两者算法大致一致,对于丢包事件判断都是以重传超时retransmission timeout和重复确认为条件,但是对于重复确认的处理两者有所不同,对于超时重传RTO情况两个算法都是将拥塞窗口降为1个MSS,然后进入慢启动阶段。
TCP Tahoe算法:如果收到三次重复确认即第四次收到相同确认号的分段确认,并且分段对应包无负载分段和无改变接收窗口的话,Tahoe算法则进入快速重传,将慢启动阈值改为当前拥塞窗口的一半,将拥塞窗口降为1个MSS,并重新进入慢启动阶段。
TCP Reno算法:如果收到三次重复确认,Reno算法则进入快速重传只将拥塞窗口减半来跳过慢启动阶段,将慢启动阈值设为当前新的拥塞窗口值,进入一个称为快速恢复的新设计阶段。
-
TCP New Reno
TCP New Reno是对TCP Reno中快速恢复阶段的重传进行改善的一种改进算法,New Reno在低错误率时运行效率和选择确认SACK相当,在高错误率仍优于Reno。
-
TCP BIC 和TCP CUBIC
TCP BIC旨在优化高速高延迟网络的拥塞控制,其拥塞窗口算法使用二分搜索算法尝试找到能长时间保持拥塞窗口最大值,Linux内核在2.6.8至2.6.18使用该算法作为默认TCP拥塞算法。
CUBIC则是比BIC更温和和系统化的分支版本,其使用三次函数代替二分算法作为其拥塞窗口算法,并且使用函数拐点作为拥塞窗口的设置值,Linux内核在2.6.19后使用该算法作为默认TCP拥塞算法。
-
TCP PRR
TCP PRR是旨在恢复期间提高发送数据的准确性,该算法确保恢复后的拥塞窗口大小尽可能接近慢启动阈值。在Google进行的测试中,能将平均延迟降低3~10%恢复超时减少5%,PRR算法后作为Linux内核3.2版本默认拥塞算法。
-
TCP BBR
TCP BBR是由Google设计于2016年发布的拥塞算法,该算法认为随着网络接口控制器逐渐进入千兆速度时,分组丢失不应该被认为是识别拥塞的主要决定因素,所以基于模型的拥塞控制算法能有更高的吞吐量和更低的延迟,可以用BBR来替代其他流行的拥塞算法。
Google在YouTube上应用该算法,将全球平均的YouTube网络吞吐量提高了4%,BBR之后移植入Linux内核4.9版本。
3.4 拥塞控制过程详解
我们以典型慢启动、拥塞避免、快速重传、快速恢复四个过程进行阐述。
-
慢启动
-
拥塞避免
-
超时重传和快速重传
-
快速恢复
4.弱网环境的AIMD特性
我们知道在网络链路中连接的数量是动态变化且数量巨大的,每一条连接都面临着一个黑盒子式的网络环境,这并不像我们平时出行时看看地图就知道哪里堵了,为了维护一个好的网络环境,每一条连接都需要遵守一些约定。
The additive-increase/multiplicative-decrease(AIMD) algorithm is a feedback control algorithm best known for its use in TCP congestion control.
AIMD combines linear growth of the congestion window with an exponential reduction when congestion is detected.
Multiple flows using AIMD congestion control will eventually converge to use equal amounts of a shared link.
The related schemes of multiplicative-increase/multiplicative-decrease (MIMD) and additive-increase/additive-decrease (AIAD) do not reach stability.简单翻译一下:线性增加乘性减少算法是一个反馈控制算法,因其在TCP拥塞控制中的使用而广为人知,AIMD将线性增加拥塞窗口和拥塞时乘性减少窗口相结合,基于AIMD的多个连接理想状态下会达到最终收敛,共享相同数量的网络带宽,与其相关的乘性增乘性减MIMD策略和增性加增性减少AIAD都无法保证稳定性。
The delay before acknowledgment packets are received (= latency) will have an impact on how fast the TCP congestion window increases (hence the throughput).When latency is high, it means that the sender spends more time idle (not sending any new packets), which reduces how fast throughput grows.
5.BBR算法基本原理
BBR算法是个主动的闭环反馈系统,通俗来说就是根据带宽和RTT延时来不断动态探索寻找合适的发送速率和发送量。
相关文献:https://queue.acm.org/detail.cfm?id=3022184
TCP BBR(Bottleneck Bandwidth and Round-trip propagation time)是由Google设计,并于2016年发布的拥塞算法,以往大部分拥塞算法是基于丢包来作为降低传输速率的信号,而BBR基于模型主动探测。
该算法使用网络最近出站数据分组当时的最大带宽和往返时间来创建网络的显式模型。数据包传输的每个累积或选择性确认用于生成记录在数据包传输过程和确认返回期间的时间内所传送数据量的采样率。
该算法认为随着网络接口控制器逐渐进入千兆速度时,分组丢失不应该被认为是识别拥塞的主要决定因素,所以基于模型的拥塞控制算法能有更高的吞吐量和更低的延迟,可以用BBR来替代其他流行的拥塞算法例如CUBIC。Google在YouTube上应用该算法,将全球平均的YouTube网络吞吐量提高了4%,在一些国家超过了14%。BBR之后移植入Linux内核4.9版本,并且对于QUIC可用。
5.1 基于丢包反馈策略可能在的问题
基于丢包反馈属于被动式机制,根源在于这些拥塞控制算法依据是否出现丢包事件来判断网络拥塞做减窗调整,这样就可能会出现一些问题:
-
丢包即拥塞
现实中网络环境很复杂会存在错误丢包,很多算法无法很好区分拥塞丢包和错误丢包,因此在存在一定错误丢包的前提下在某些网络场景中并不能充分利用带宽。 -
缓冲区膨胀问题BufferBloat
网络连接中路由器、交换机、核心网设备等等为了平滑网络波动而存在缓冲区,这些缓存区就像输液管的膨胀部分让数据更加平稳,但是Loss-Based策略在最初就像网络中发生数据类似于灌水,此时是将Buffer全部算在内的,一旦buffer满了,就可能出现RTT增加丢包等问题,就相当于有的容量本不该算在其中,但是策略是基于包含Buffer进行预测的,特别地在深缓冲区网络就会出现一些问题。 -
网络负载高但无丢包事件
假设网络中的负载已经很高了,只要没有丢包事件出现,算法就不会主动减窗降低发送速率,这种情况下虽然充分利用了网络带宽,同时由于一直没有丢包事件出现发送方仍然在加窗,表现出了较强的网络带宽侵略性,加重了网络负载压力。 -
高负载丢包
高负载无丢包情况下算法一直加窗,这样可以预测丢包事件可能很快就出现了,一旦丢包出现窗口将呈现乘性减少,由高位发送速率迅速降低会造成整个网络的瞬时抖动性,总体呈现较大的锯齿状波动。 -
低负载高延时丢包
在某些弱网环境下RTT会增加甚至出现非拥塞引起丢包,此时基于丢包反馈的拥塞算法的窗口会比较小,对带宽的利用率很低,吞吐量下降很明显,但是实际上网络负载并不高,所以在弱网环境下效果并不是非常理想。
5.2 TCP BBR算法基本原理
前面我们提到了一些Loss-Based算法存在的问题,TCP BBR算法是一种主动式机制,简单来说BBR算法不再基于丢包判断并且也不再使用AIMD线性增乘性减策略来维护拥塞窗口,而是分别采样估计极大带宽和极小延时,并用二者乘积作为发送窗口,并且BBR引入了Pacing Rate限制数据发送速率,配合cwnd使用来降低冲击。
5.2.1 一些术语
- BDPBDP是Bandwidth-Delay Product的缩写,可以翻译为带宽延时积,我们知道带宽的单位是bps(bit per second),延时的单位是s,这样BDP的量纲单位就是bit,从而我们知道BDP就是衡量一段时间内链路的数据量的指标。这个可以形象理解为水管灌水问题,带宽就是水管的水流速度立方米/s,延时就是灌水时间单位s,二者乘积我们就可以知道当前水管内存储的水量了,这是BBR算法的一个关键指标,来看一张陶辉大神文章中的图以及一些网络场景中的BDP计算:
-
长肥网络
我们把具有长RTT往返时间和高带宽的网络成为长肥网络或者长肥管道,它的带宽延时积BDP很大大,这种网络理论上吞吐量很大也是研究的重点。
-
TCP Pacing机制
可以简单地理解TCP Pacing机制就是将拥塞控制中数据包的做平滑发送处理,避免数据的突发降低网络抖动。
5.2.2 带宽和延时的测量
BBR算法的一些思想在之前的基于延时的拥塞控制算法中也有出现,其中必有有名的是TCP WestWood算法。
TCP Westwood改良自New Reno,不同于以往其他拥塞控制算法使用丢失来测量,其通过对确认包测量来确定一个合适的发送速度,并以此调整拥塞窗口和慢启动阈值。其改良了慢启动阶段算法为敏捷探测和设计了一种持续探测拥塞窗口的方法来控制进入敏捷探测,使链接尽可能地使用更多的带宽。TCP WestWood算法也是基于带宽和延时乘积进行设计的,但是带宽和延时两个指标无法同时测量,因为这两个值是有些矛盾的极值,要测量最大带宽就要发送最大的数据量但是此时的RTT可能会很大,如果要测量最小的RTT那么久意味着数据量非常少最大带宽就无法获得。
5.2.3 发送速率和RTT曲线
前面提到了BBR算法核心是寻找BDP最优工作点,在相关论文中给出了一张组合的曲线图,我们一起来看下:
这张图是由两个图组合而成,目前是展示[数据发送速率vs网络数据]和[RTTvs网络数据]的关系,横轴是网络数据数量。
-
app limit应用限制阶段
在这个阶段是应用程序开始发送数据,目前网络通畅RTT基本保持固定且很小,发送速率与RTT成反比,因此发送速率也是线性增加的,可以简单认为这个阶段有效带宽并没有达到上限,RTT是几乎固定的没有明显增长。 -
band limit带宽限制阶段
随着发送速率提高,网络中的数据包越来越多开始占用链路Buffer,此时RTT开始增加发送速率不再上升,有效带宽开始出现瓶颈,但是此时链路中的缓存区并没有占满,因此数据还在增加,RTT也开始增加。 -
buffer limit缓冲区限制阶段
随着链路中的Buffer被占满,开始出现丢包,这也是探测到的最大带宽,这个节点BDP BufferSize也是基于丢包的控制策略的作用点。
3.一些看法
5.2.4 BBR算法的主要过程
BBR算法和CUBIC算法类似,也同样有几个过程:StartUp、Drain、Probe_BW、Probe_RTT,来看下这几个状态的迁移情况:
-
StartUp慢启动阶段
BBR的慢启动阶段类似于CUBIC的慢启动,同样是进行探测式加速区别在于BBR的慢启动使用2ln2的增益加速,过程中即使发生丢包也不会引起速率的降低,而是依据返回的确认数据包来判断带宽增长,直到带宽不再增长时就停止慢启动而进入下一个阶段,需要注意的是在寻找最大带宽的过程中产生了多余的2BDP的数据量,关于这块可以看下英文原文的解释:
To handle Internet link bandwidths spanning 12 orders of magnitude, Startup implements a binary search for BtlBw by using a gain of 2/ln2 to double the sending rate while delivery rate is increasing. This discovers BtlBw in log2BDP RTTs but creates up to 2BDP excess queue in the process.
-
Drain排空阶段
排空阶段是为了把慢启动结束时多余的2BDP的数据量清空,此阶段发送速率开始下降,也就是单位时间发送的数据包数量在下降,直到未确认的数据包数量
-
ProbeBW带宽探测阶段
经过慢启动和排空之后,目前发送方进入稳定状态进行数据的发送,由于网络带宽的变化要比RTT更为频繁,因此ProbeBW阶段也是BBR的主要阶段,在探测期中增加发包速率如果数据包ACK并没有受影响那么就继续增加,探测到带宽降低时也进行发包速率下降。
-
ProbeRTT延时探测阶段
前面三个过程在运行时都可能进入ProbeRTT阶段,当某个设定时间内都没有更新最小延时状态下开始降低数据包发送量,试图探测到更小的MinRTT,探测完成之后再根据最新数据来确定进入慢启动还是ProbeBW阶段。
5.3 TCP-BBR算法效果
有一些文章认为BBR有鲜明的特点,把拥塞控制算法分为BBR之前和BBR之后,可见BBR还是有一定影响,但是BBR算法也不是银弹,不过可以先看看BBR算法在谷歌推动下的一些应用效果,其中包括吞吐量、RTT、丢包率影响: