TCP慢启动与拥塞避免算法

来源:互联网 发布:java length 中文 编辑:程序博客网 时间:2024/05/16 11:43
路由器因无法处理高速率到达的流量而被迫丢弃数据信息的现象称为拥塞。当路由器处于上述状态时,就表明发生了拥塞。


TCP拥塞检测

针对丢包情况,TCP采取的首要机制是重传,包括超时重传和快速重传。考虑如下情形,当网络处于拥塞崩溃状态时,共用一条网络传输路径的多个TCP连接却需要重传更多数据包,可想而知,结果只会更糟,所以这种情况应该避免。
当拥塞状况出现时,我们可以减缓TCP发送端的发送速率;若拥塞情况有所缓解,可以检测和使用新的可用带宽。然而这在互联网中很难做到,因为对于TCP发送方来说,没有一个精确的方法去知晓中间路由器的状态。换言之,没有一个明确的信号告知拥塞状况已发生。典型的TCP只有在断定拥塞发生的情况下,才会采取相应的行动。推断是否发生拥塞,通常看是否有丢包的情况发生。在TCP中,丢包也被用作判断拥塞发生与否的指标,用来衡量是否实施相应的响应措施(即以某种方式减缓发送)。从20世纪80年代起,TCP一直沿用这种方法。其他拥塞探测方法,包括时延测量与显示拥塞控制通知(ECN),使得TCP能在丢包发生前检测拥塞。

减缓TCP发送

根据接收方剩余缓存空间大小,在TCP头部设置了通知窗口大小字段,该数值是TCP发送方调节发送速率的依据。当接收速率或网络传输速率过慢时,我们需要降低发送速率。为实现上述操作,基于对网络传输能力的估计,可以在发送端引入一个窗口控制变量,确保发送窗口大小不超过接收端能力和网络传输能力,即TCP发送端的发送速率等于接收速率和传输速率两者中较小值。
反映网络传输能力的变量成为拥塞窗口,记作cwnd。因此,发送端实际窗口W就是接收端通知窗口awnd和拥塞窗口cwnd的较小者:
           W=min(cwnd,awnd)
根据上述等式,TCP发送端发送的数据中,还没有收到ACK回复的数据量不能多于W(以包或字节为单位)。这种已经发出但还未经确认的数据量大小有时称为在外数据值,它总是小于等于W。通常,W可以以包或字节为单位。
因为网络和接收端状况会随时间变化,相应地,awnd和cwnd的数值也随之改变。另外,由于缺少显示拥塞控制的信号,TCP发送方无法直接获得cwnd的“准确值”。因此,变量W、cwnd、awnd的值都要根据经验设定并需动态调节。此外,W的值不能过大或过小----我们希望其接近带宽延迟积,也称作最佳窗口大小。W反映网络中可存储的待发送数据量大小,其计算值等于RTT与链路中最小同行速率的乘积。通常的策略是,为使网络资源得到高效利用应保证在网络传输中的数据量达到BDP。但若在传输数据值远高于BDP时,会引入不必要的延时,所以这是不可取的。在网络中如何确定一个连接的BDP是难点,需要考虑诸多因素,如路由、时延、统计复用水平随时间变化性等。

经典算法
当一个新的TCP连接建立之初,还无法获知可用的传输资源,所以cwnd的初始值也无法确定。TCP通过与接收端交换一个数据包就能获得awnd的值,不需要任何明确的信号。显而易见,获得xwnd最佳值的唯一方法是以越来越快的速率不断发送数据,直到出现数据包丢失为止。这时考虑立即以可用的最大速率发送,或是慢速启动发送。由于多个TCP连接共享一个网络传输路径,以全速启动会影响其他连接的传输性能,所以通常会有特定的算法来避免过快启动,直至稳定传输后才会运行相应的其他算法。
TCP的两个核心算法:慢启动和拥塞避免,这两个算法是基于保守恒和ACK时钟原理


1.慢启动

当一个新的TCP连接建立或检测到由重传超时(RTO)导致的丢包时,需要执行慢启动。TCP发送端长时间处于空闲状态也可能调用慢启动算法。慢启动的目的是,使TCP在用拥塞避免探寻更多可用带宽之前得到cwnd值,以及帮助TCP建立ACK时钟。通常,TCP在建立新连接时执行慢启动,直至有丢包时,执行拥塞避免算法进入稳定状态。
在传输初始阶段,由于未知网络传输能力,需要缓慢探测可用传输资源,防止短时间内大量数据注入导致拥塞。慢启动算法正是针对这一问题而设计。在数据传输之初或者重传计时器检测到丢包后,需要执行慢启动。
TCP以发送一定数目的数据段开始慢启动(在SYN交换之后),称为初始窗口(IW)。IW的值初始设为一个SMSS(发送方的最大段大小),计算公式如下:
    IW=2*(SMSS)且小于等于2个数据段(当SMSS>2190字节)
    IW=3*(SMSS)且小于等于3个数据段(当2190>=SMSS>1095字节)
    IW=4*(SMSS)且小于等于4个数据段(其他)
上述IW的计算方式可能使得初始窗口为几个数据包大小(如3个或4个),为简单起见,只讨论IW=1SMSS的情况。TCP连接初始的cwnd=1SMSS,意味着初始可用窗口W也为1SMSS。注意到大部分情况下,SMSS为接收方的MSS(最大段大小)和路径MTU(最大传输单元)两者中较小值。
假设没有出现丢包情况且每个数据包都有相应的ACK,第一个数据段的ACK到达,说明可发送一个新的数据段。每接收到一个好的ACK响应,慢启动算法会以min(N,SMSS)来增加cwnd值。这里的N是指在未经确认的传输数据中能通过这一“好的ACK”确认字节数。所谓"好的ACK"是指新接收的ACK号大于之前收到的ACK。
因此,在接收到一个数据段的ACK之后,通常cwnd值会增加到2,接着会发送两个数据段。如果成功收到相应的新的ACK,cwnd会由2变4,由4变8,以此类推。一般情况下,假设没有丢包且每个数据包都有相应ACK,在k轮后W的值为W=2^k,即k=logW,需要k个RTT时间操作窗口才能达到W大小。这种增长看似很快,但若与一开始就允许以最大可用速率发送相比,仍显缓慢。

2.拥塞避免
在连接建立之初以及由超市判定丢包发生的情况下,需要执行慢启动操作。在慢启动阶段,cwnd会快速增长,帮助确立一个慢启动阈值。一旦达到阈值,就意味着可能有更多可用的传输资源。如果立即全部占用这些资源,将会使共享路由器队列的其他连接出现严重的丢包和重传情况,从而导致整个网络性能不稳定。
为了得到更多的传输资源而不导致影响其他连接传输,TCP实现了拥塞避免算法。一旦确立慢启动阈值,TCP会进入拥塞避免阶段,cwnd每次的增长值近似于成功传输的数据段大小。这种随时间线性增长方式与慢启动的指数增长相比缓慢许多。更准确地说,每接收一个新的ACK,cwnd都做以下更新:
                   cwnd(t+1)=cwnd(t)+SMSS*SMSS/cwnd(t)
随着每个新的ACK到达,cwnd会有相应的小幅增长(取决于上式中的k值),整体增长率呈现轻微的次线性。我们通常认为拥塞避免阶段的窗口随时间线性增长,而慢启动阶段呈指数增长。


3.慢启动与拥塞避免的选择

在通常操作中,某个TCP连接总是选择运行慢启动和拥塞避免中的一个,不会出现两者同时进行的情况。现在考虑,在任一给定时刻如何决定选用哪种算法。我们已经知道,慢启动是在连接建立之初以及超时发生时执行的。那么决定使用慢启动还是拥塞避免地关键因素是什么呢?
慢启动阈值和cwnd的关系是决定采用慢启动还是拥塞避免的界线。当cwnd<ssthresh,使用慢启动算法;当cwnd>ssthresh,需要执行拥塞避免。当两者相等时,任何一种算法都可以使用。因此可以得到,慢启动和拥塞避免之间最大区别在于,当新的ACK到达时,cwnd这样增长。当然慢启动阈值不是固定的,而是随时间改变的。它的主要目的是,在没有丢包发生的情况下,记住上一次"最好的"操作窗口估计值。换言之,它记录TCP最优窗口估计值的下界。