【Network】TCP 的拥塞控制(Congestion Handling)

Posted by 西维蜀黍 on 2019-05-08, Last Modified on 2021-09-21

TCP的拥塞控制(Congestion Handling)

拥塞(Congestion):即对资源的需求超过了可用的资源。若网络中许多资源同时供应不足,网络的性能就要明显变坏,整个网络的吞吐量随之负荷的增大而下降。

拥塞控制(Congestion Handling):防止过多的数据注入到网络中,最终避免网络中的路由器或链路过载。拥塞控制所要做的都有一个前提:网络能够承受现有的网络负荷。拥塞控制是一个全局性的过程,涉及到所有的主机、路由器,以及与降低网络传输性能有关的所有因素。

几种拥塞控制方法

  • 慢开始(slow-start)
  • 拥塞避免(congestion avoidance)
  • 快重传(fast retransmit)
  • 快恢复(fast recovery)

慢开始算法和拥塞避免算法

发送方维持一个拥塞窗口 cwnd(congestion window)的状态变量。拥塞窗口的大小取决于网络的拥塞程度,并且动态地在变化。发送方让自己的发送窗口等于拥塞。

发送方控制拥塞窗口的原则是:只要网络没有出现拥塞(及时收到了对已发送报文段的确认),拥塞窗口(cwnd)就再增大一些,以便把更多的分组发送出去。但只要网络出现拥塞,拥塞窗口就减小一些,以减少注入到网络中的分组数

慢开始算法

当发送方主机开始发送数据时,如果立即大量数据字节注入到网络,那么就有可能引起网络拥塞,因为现在并不清楚网络的负荷情况。

因此,较好的方法是先探测一下,即由小到大逐渐增大发送窗口,也就是说,发送方主机由小到大逐渐增大拥塞窗口数值。

通常在刚刚开始发送报文段时,发送方主机先把拥塞窗口(cwnd)设置为一个最大报文段(MSS)的数值。而在每收到一个对已发送报文段的确认(本质上是一个ACK报文段)后,把拥塞窗口增加至多一个MSS的数值。用这样的方法逐步增大发送方的拥塞窗口(cwnd) ,可以使分组注入到网络的速率更加合理。

每经过一个传输轮次,拥塞窗口(cwnd)就加倍。一个传输轮次所经历的时间其实就是往返时间RTT。不过“传输轮次”更加强调:把拥塞窗口(cwnd)所允许发送的报文段都连续发送出去,并收到了对已发送的最后一个字节的确认。

另,慢开始的“慢”并不是指cwnd的增长速率慢,而是指在TCP开始发送报文段时先设置cwnd=1,使得发送方在开始时只发送一个报文段(目的是试探一下当前网络的拥塞情况),然后再逐渐增大cwnd。

为了防止拥塞窗口(cwnd)增长过大引起网络拥塞,还需要设置一个慢开始门限(ssthresh)状态变量。

慢开始门限(ssthresh)的用法如下:

  • 当 cwnd < ssthresh 时,使用上述的慢开始算法。
  • 当 cwnd > ssthresh 时,停止使用慢开始算法而改用拥塞避免算法。
  • 当 cwnd = ssthresh 时,既可使用慢开始算法,也可使用拥塞控制避免算法。

拥塞避免算法

让拥塞窗口cwnd缓慢地增大,即每经过一个传输轮次(一个传输轮次等于一个往返时间RTT),就把发送方的拥塞窗口cwnd加1,而不是加倍。这样拥塞窗口cwnd按线性规律缓慢增长,比慢开始算法的拥塞窗口增长速率缓慢得多。

无论在慢开始阶段还是在拥塞避免阶段,只要发送方判断网络出现拥塞(其判断依据是没有收到确认),就要把慢开始门限(ssthresh)设置为出现拥塞时的发送方窗口值的一半(但不能小于2)。然后把拥塞窗口cwnd重新设置为1,执行慢开始算法。这样做的目的就是要迅速减少主机发送到网络中的分组数,使得发生拥塞的路由器有足够时间把队列中积压的分组处理完毕。

如下图,用具体数值说明了上述拥塞控制的过程。现在发送窗口的大小和拥塞窗口一样大。

  1. 当TCP连接进行初始化时,把拥塞窗口(cwnd)值置为1。前面已说过,为了便于理解,图中的窗口单位不使用字节而使用报文段的个数。慢开始门限(ssthresh)的初始值设置为16个报文段,即 cwnd = 16 。
  2. 在执行慢开始算法时,把拥塞窗口(cwnd)值的初始值为1。以后发送方每收到一个对已发送报文段的确认ACK报文段后,就把拥塞窗口值加1,然后开始下一轮的传输(图中横坐标为传输轮次)。因此拥塞窗口(cwnd)值随着传输轮次按指数规律增长。当拥塞窗口(cwnd)值增长到慢开始门限值(ssthresh)时(即当cwnd=16时),就改为执行拥塞控制算法,此后拥塞窗口(cwnd)值按线性规律增长。
  3. 假定拥塞窗口(cwnd)值增长到24时,网络出现超时(这很可能就是网络发生拥塞了)。更新后的慢开始门限(ssthresh)值变为12(即变为出现超时时的拥塞窗口数值24的一半),拥塞窗口(cwnd)值被重新设置为1,并执行慢开始算法。当cwnd=ssthresh=12时,改为执行拥塞避免算法,拥塞窗口按线性规律增长,每经过一个往返时间增加一个MSS的大小。

强调:“拥塞避免”并非指完全能够避免了拥塞。利用以上的措施要完全避免网络拥塞还是不可能的。“拥塞避免”是说在拥塞避免阶段将拥塞窗口控制为按线性规律增长,使网络比较不容易出现拥塞。

快重传(Fast retransmit)

快重传算法首先要求:接收方每收到一个失序的报文段后,就立即发出一个重复确认(为的是使发送方尽早知道有报文段没有到达接收方),而不要等到自己发送数据时才进行捎带确认。

如果数据发送方连续收到3个或3个以上重复的ACK,会判定此报文段丢失,并进行重新传递,而不会等待RTO(Retransmission Timeout,重传超时时间),这就叫做快速重传。

接收方收到了M1和M2后都分别发出了确认。现在假定接收方没有收到M3但接着收到了M4。

显然,接收方不能确认M4,因为M4是收到的失序报文段。根据 可靠传输原理,接收方可以什么都不做,也可以在适当时机发送一次对M2的确认。

但按照快重传算法的规定,接收方应及时发送对M2的重复确认,这样做可以让 发送方及早知道报文段M3没有到达接收方。发送方接着发送了M5和M6。接收方收到这两个报文后,也还要再次发出对M2的重复确认。这样,发送方共收到了 接收方的四个对M2的确认,其中后三个都是重复确认。

快重传算法还规定,发送方只要一连收到三个重复确认就应当立即重传对方尚未收到的报文段M3,而不必 继续等待M3设置的重传计时器到期。

由于发送方尽早重传未被确认的报文段,因此采用快重传后可以使整个网络吞吐量提高约20%。

快恢复(Fast recovery)

与快重传配合使用的还有快恢复算法,其过程有以下两个要点:

  • 当发送方连续收到三个重复确认,就执行“乘法减小”算法,把慢开始门限ssthresh减半。
  • 与慢开始不同之处是,现在不执行慢开始算法(即拥塞窗口cwnd现在不设置为1),而是把cwnd值设置为慢开始门限ssthresh减半后的数值,然后开始执行拥塞避免算法(“加法增大”),使拥塞窗口缓慢地线性增大。

Reference