我是靠谱客的博主 悦耳玉米,最近开发中收集的这篇文章主要介绍TCP/IP卷一:86---TCP拥塞控制之(慢启动、拥塞避免技术与经典算法(Tahoe、Reno以及快速恢复算法))一、慢启动二、拥塞避免三、慢启动和拥塞避免的选择四、Tahoe、Reno以及快速恢复算法五、标准TCP,觉得挺不错的,现在分享给大家,希望可以做个参考。
概述
- 现在我们讨论TCP的两个核心算法:慢启动和拥塞避免
- 这两个算法是基于包守恒和ACK时钟原理,最早在Jacobson [J88]的经典论文里被正式提出。几年后,Jacobson对拥塞避免算法提出了改进[J90]
- 这两个算法不是同时运行的——在任一给定时刻,TCP只运行 一个算法,但两者可以相互切换
- 下面我们将详细讨论这两个算法,包括如何使用以及对算法的改进。每个TCP连接都能独立运行这两个算法
一、慢启动
- 何时使用慢启动:
- 当一个新的TCP连接建立或检测到由重传超时(RTO)导致的丢包时,需要执行慢启动
- TCP发送端长时间处于空闲状态也可能调用慢启动算法
- 慢启动的目的是:
- 使TCP在用拥塞避免探寻更多可用带宽之前得到cwnd值,以及帮助TCP建立ACK时钟
- 通常,TCP在建立新连接时执行慢启动,直至有丢包时,执行拥塞避免算法(见下面的拥塞避免)进入稳定状态
- 下文引自[RFC5681]:
初始窗口(IW)
- TCP以发送一定数目的数据段开始慢启动(在SYN交换之后),称为初始窗口(Initial Window,IW)
- IW的值初始设为一个SMSS(发送方的最大段大小),但在[RFC5681]中设为一个稍大的值,计算公式如下:
- 上述IW的计算方式可能使得初始窗口为几个数据包大小(如3个或4个)
- 为简单起见,我们只讨论IW= 1 SMSS的情况。TCP连接初始的cwnd= 1 SMSS,意味着初始可用窗口W也为1 SMSS。注意到大部分情况下,SMSS为接收方的MSS(最大段大小)和路径MTU(最大传输单元)两者中较小值
cwnd的初始化(线性增长)
- 因此,在接收到一个数据段的ACK后,通常cwnd值会增加到2,接着会发送两个数据段。如果成功收到相应的新的ACK,cwnd会由2变4,由4变8,以此类推......
- 一般情况下,假设没有丢包且每个数据包都有相应ACK,在k轮后W的值为W=,即k= log2W,需要k个RTT时间操作窗口才能达到W大小
- 这种增长看似很快(以指数函数增长),但若与一 开始就允许以最大可用速率(即接收方通知窗口大小)发送相比,仍显缓慢。 (W不会超过awnd)
慢启动阀值
- 如果假设某个TCP连接中接收方的通知窗口非常大(比如说,无穷大),这时cwnd就是影响发送速率的主要因素(设发送方有较大发送需求)
- 如前所述,cwnd会随着RTT呈指数增长。因此,最终cwnd(W也如此)会增至很大,大量数据包的发送将导致网络瘫痪(TCP吞吐量与,W/RTT成正比)
- 当发生上述情况时,cwnd将大幅度减小(减至原值一半)。这是TCP由慢启动阶段至拥塞避免阶段的转折点,与cwnd和慢启动阂值(sIow start threshold,ssthresh)相关
慢启动图示
- 图左描述了慢启动操作:数值部分以RTT为单位。假设该连接首先发送一个包(图上部),返回一个ACK,接着在第二个RTT时间里发送两个包,会接收到两个ACK。TCP发送方每接收一个ACK就会执行一次cwnd的增长操作,以此类推
- 右图描述了cwnd随时间增长的指数函数:图中另一条曲线显示了每两个数据包收到一个ACK时cwnd的增长情况。通常在ACK延时情况下会采用这种方式,这时的cwnd仍以指数增长,只是增幅不是很大。正因ACK可能会延时到达,所以一些TCP操作只在慢启动阶段完成后才返回ACK。Linux系统中,这被称为快速确认( “快速ACK模式”),从内核版本2.4.4开始,快速确认 一直是基本TCP/IP协议栈的一部分
二、拥塞避免
为什么设计拥塞避免
- 如上所述,在连接建立之初以及由超时判定丢包发生的情况下,需要执行慢启动操作。在慢启动阶段,cwnd会快速增长,帮助确立一个慢启动阈值。一旦达到阈值,就意味着可能有更多可用的传输资源。如果立即全部占用这些资源,将会使共享路由器队列的其他连接出现严重的丢包和重传情况,从而导致整个网络性能不稳定
- 为了得到更多的传输资源而不致影响其他连接传输,TCP实现了拥塞避免算法
算法分析
- 一旦确立慢启动阈值,TCP进入拥塞避免阶段,cwnd每次的增长值近似于成功传输的数据段大小。 这种随时间线性增长方式与慢启动的指数增长相比缓慢许多
- 更准确地说,每接收一个新的 ACK,cwnd会做以下更新:
- 分析上时,假设字节分k段发送没在接收到第一个ACK后,cwnd的值增长了1/K倍:
图示分析
- 随着每个新的ACK到达,cwnd会有相应的小幅增长(取决于上式中的居值),整体增长率呈现轻微的次线性。尽管如此,我们通常认为拥塞避免阶段的窗口随时间线性增长(见下图),而慢启动阶段呈指数增长(见慢启动中的图片)。这个函数也称为“累加增长”,因为每成功接收到相应数据,cwnd就会增加一个特定值(这里大约是一个包大小)
- 左图描述了拥塞避免操作。数值部分仍是以RTT为单位。假设连接发送了4个数据包(图上方),返回了4个ACK,cwnd可以有相应的增长。在第2个RTT阶段,增长可达到整数值,使得cwnd增加一个SMSS,这样可以继续发送一个新的数据包
- 右图描绘了cwnd随时间近似呈线性增长。另一曲线模拟ACK延时,显示了每两个数据包收到一个ACK时cwnd的增长情况。这时的cwnd仍近似呈线性增长,只是增幅不是很大
- 拥塞避免算法假设由比特错误导致包丢失的概率很小(远小于1%),因此有丢包发生就表明从源端到目的端必有某处出现了拥塞。如果假设不成立:
- 比如在无线网络中,那么即使没有拥塞TCP传输也会变慢
- 另外,cwnd的增大可能会经历多个RTT,这就需要有充裕的网络资源,并得到高效利用
- 这些问题还有很大的研究空间,以后我们将会讨论其中一些方法
三、慢启动和拥塞避免的选择
- 在通常操作中,某个TCP连接总是选择运行慢启动和拥塞避免中的一个,不会出现两者同时进行的情况。现在我们考虑,在任一给定时刻如何决定选用哪种算法。我们已经知道,慢启动是在连接建立之初以及超时发生时执行的。那么决定使用慢启动还是拥塞避免的关键因素是什么呢?
慢启动阈值(ssthresh)
- 前面我们已经提到过慢启动阈值。这个值和cwnd的关系是决定采用慢启动还是拥塞避免的界线:
- 当cwnd < ssthresh,使用慢启动算法
- 当cwnd > ssthresh,需要执行拥塞避免
- 而当两者相等时,任何一种算法都可以使用
- 由上面描述可以得出,慢启动和拥塞避免之间最大的区别在于:当新的ACK到达时,cwnd怎样增长
- 有趣的是,慢启动阈值不是固定的,而是随时间改变的。它的主要目的是,在没有丢包发生的情况下,记住上一次“最好的”操作窗口估计值。换言之,它记录TCP最优窗口估计值的下界
- 慢启动阈值的初始值可任意设定(如awnd或更大),这会使得TCP总是以慢启动状态开始传输
- 当有重传情况发生,无论是超时重传还是快速重传,ssthresh会按下式改变:
- 我们已经知道,如果出现重传情况:
- TCP会认为操作窗口超出了网络传输能力范围。这时会将慢启动阈值(ssthresh)减小至当前窗口大小的一半(但不小于2*SMSS),从而减小最优窗口估计值
- 这样通常会导致ssthresh减小,但也有可能会使之增大。分析TCP拥塞避免的操作流程,如果整个窗口的数据都成功传输,那么cwnd值可以近似增大1 SMSS。因此,若cwnd在一段时间范围内已经增大,将ssthresh设为整个窗口大小的一半可能使其增大。这种情况发生在当TCP探测到更多可用带宽时
- 在慢启动和拥塞避免结合的情况下,ssthresh和cwnd的相互作用使得TCP拥塞处理行为显现其独有特性
- 下面我们探讨将两者结合的完整的算法
四、Tahoe、Reno以及快速恢复算法
- 至此讨论的慢启动和拥塞避免算法,组成了TCP拥塞控制算法的第一部分。它们于20世纪80年代末期在加州大学伯克利分校的4.2版本的UNIx系统中被提出,称为伯克利软件版本,或BSD UNIX。至此开始了以美国城市名命名各个TCP版本的习惯,尤其是那些赌博 合法的城市
Tahoe
- 4.2版本的BSD(称为Tahoe)包含了一个TCP版本,它在连接之初处于慢启动阶段,若检测到丢包,不论由于超时还是快速重传,都会重新进入慢启动状态。有丢包情况发生时,Tahoe简单地将cwnd减为初始值(当时设为1 SMSS)以达到慢启动目的,直至cwnd增长为ssthresh
- 这种方法带来的一个问题是,对于有较大BDP的链路来说,会使得带宽利用率低下。因为TCP发送方经重新慢启动,回归到的还是未丢包状态(cwnd启动初始值设置过小)。
- 为解决这一问题,针对不同的丢包情况,重新考虑是否需要重回慢启动状态。若是由重复ACK引起的丢包(引发快速重传),cwnd值将被设为上一个ssthresh,而非先前的1 SMSS。(在大多数TCP版本中,超时仍是引发慢启动的主要原因)这种方法使得TCP无须重新慢启动,而只要把传输速率减半即可
Reno
- 进一步讨论较大BDP链路的情况,结合之前提到的包守恒原理,我们可以得出结论,只要接收到ACK回复(包括重传ACK),就有可能传输新的数据包
- BSD UNIX的4.3 BSD Reno版中的快速恢复机制就是基于上述结论。在恢复阶段,每收到一个ACK,cwnd就能(临时)增长1 SMSS,相应地就意味着能发送一个新的数据包。因此拥塞窗口在一段时间内会急速增长,直到接收一个好的ACK。不重复的(“好的”) ACK表明TCP结束恢复阶段,拥塞已减少到之前状态
- TCP Reno算法得到了广泛应用,并成为“标准TCP”的基础
五、标准TCP
- 尽管究竟哪些构成了“标准” TCP还存在争议,但我们讨论过的上述算法毋庸置疑都属于标准TCP。慢启动和拥塞避免算法通常结合使用,[RFC5681]给出了其基本方法。这个规范并不要求严格使用这些精确算法,TCP实现过程仅利用其核心思想。
- 总结[RFC5681]中的结合算法,在TCP连接建立之初首先是慢启动阶段(cwnd = IW),ssthresh通常取一较大值(至少为awnd)。当接收到一个好的ACK (表明新的数据传输成功),cwnd会相应更新:
- 当收到三次重复ACK(或其他表明需要快速重传的信号)时,会执行以下行为:
- 1.ssthresh更新为大于等式(上面慢启动阈值中的等式)中的值
- 2.启用快速重传算法,将cwnd设为(ssthresh + 3*SMSS)
- 3.每接收一个重复ACK,cwnd值暂时增加1 SMSS
- 4.当接收到一个好的ACK,将cwnd重设为ssthresh
- 以上第2步和第3步构成了快速恢复:
- 步骤2设置cwnd大小,首先cwnd通常会被减为之前值的一半。然后,考虑到每接收一个重复ACk,就意味着相应的数据包已成功传输(因此新的数据包就有发送机会),cwnd值会相应地暂时增大。这一步也可能出现cwnd加速递减的情况,因为通常cwnd会乘以某个值(这里取0.5)来形成新的cwnd
- 步骤3维持cwnd的增大过程,使得发送方可以继续发送新的数据包(在不超过awnd的情况下)
- 步骤4假设TCP已完成恢复阶段,所以cwnd的临时膨胀也消除了(有时称这一步为“收缩”)
- 以下两种情况总会执行慢启动:新连接的建立以及出现重传超时。当发送方长时间处于空闲状态,或者有理由怀疑cwnd不能精确反映网络当前拥塞状态(参见下一篇文章中的“拥塞窗口校验”)时,也可能引发慢启动。在这种情况下,cwnd的初始值将被设为重启窗口(RW)。在文献[RFC5681] 中,推荐RW值为RW=min(IW,cwnd)。其他情况下,慢启动中cwnd初始设为IW
最后
以上就是悦耳玉米为你收集整理的TCP/IP卷一:86---TCP拥塞控制之(慢启动、拥塞避免技术与经典算法(Tahoe、Reno以及快速恢复算法))一、慢启动二、拥塞避免三、慢启动和拥塞避免的选择四、Tahoe、Reno以及快速恢复算法五、标准TCP的全部内容,希望文章能够帮你解决TCP/IP卷一:86---TCP拥塞控制之(慢启动、拥塞避免技术与经典算法(Tahoe、Reno以及快速恢复算法))一、慢启动二、拥塞避免三、慢启动和拥塞避免的选择四、Tahoe、Reno以及快速恢复算法五、标准TCP所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复