33-tcp拥塞控制——拥塞避免

1. 慢开始算法的增长速率

  上一篇慢启动没有介绍拥塞窗口的增量,初始设置,因为我觉得放在拥塞避免中介绍更合适,先说拥塞窗口的增量吧。我们从上一篇中的例子中的每一传输轮次的往返时间(RTT)来看拥塞窗口cwnd的大小,就会发现它的增长规律:

开始     —>    cwnd = 100
经过RR1后   —>    cwnd = 100 x 2 = 200 = 2001
经过RTT2后  —>    cwnd = 200 x 2 = 400 = 200 2

  需要说明的是,以上的拥塞窗口cwnd增长速率是我们在假定每发送一个报文就回一个ACK的策略下,对于每个ACK,cwnd就增长一个mss,在这种策略下,增长是2的乘方。

  而如果是在累积确认策略下,拥塞窗口的增长速率则要比上面这种策略慢一些。比如现在发送了三个报文,然后只回了一个ACK确认(针对这三个报文的累积确认),那么cwnd就只增长一个mss,而不是3个mss,在这种策略下,虽然不再是2的乘方,但是仍然是按指数来增长

  当然,慢开始肯定是不能无限增长下去,一定要有一个门限来停止拥塞窗口增长阶段。因此发送方维护了一个慢开始门限状态变量ssthresh,用法如下:

  1. 当cwnd < ssthresh时,使用上述的慢开始算法。
  2. 当cwnd > ssthresh时,停止使用慢开始算法,而改用拥塞避免算法。
  3. 当cwnd = ssthresh时,既可以使用慢开始算法,也可以使用拥塞避免算法。


2. 拥塞避免算法——加法增大

  在慢开始算法中,为了防止拥塞窗口cwnd增长过大而引起网络拥塞,tcp会通过拥塞避免算法来控制拥塞窗口的增长,使拥塞窗口cwnd按加法规律增长,即拥塞避免:加法增大,而不是按上面的指数规律。

  当拥塞窗口cwnd > 门限值ssthresh时,停止使用慢开始算法,而改用拥塞避免算法,而拥塞避免算法的思路是:每经过一个往返时间(RTT)就把拥塞窗口cwnd加1(注意:这个1是指一个最大报文长度mss),可以看出这个增长是基于RTT。也就是说,在拥塞避免阶段,cwnd增长就按线性规律缓慢增长,这样就比慢开始算法中的拥塞窗口增长速率缓慢很多。

  下面通过一个例子来说明拥塞避免算法的增长规律,只不过这次我们是按照拥塞避免算法的思路:从往返时间RTT的角度来看cwnd的大小,就会发现速率是按加法规律增长的,假设此时cwnd = m,如图1所示:

33-tcp拥塞控制——拥塞避免
图1—加法增大算法


3. 拥塞避免算法——乘法减小

  通过上图可知,在拥塞避免算法中,拥塞窗口大小是按照线性加法规律增长的,直到检测到网络拥塞为止,则使用拥塞避免算法:乘法减小。

  乘法减小是指:无论在慢开始阶段还是在拥塞避免阶段,只要出现超时重传(可能是网络出现拥塞),就把慢开始中的门限值ssthresh减半,也就是设置门限值为发送方的拥塞窗口的一半,再重新设置拥塞窗口的初始值,执行慢开始算法。来看下面一个例子,这是一个比较综合的例子,包括慢开始和拥塞避免两个阶段。

33-tcp拥塞控制——拥塞避免
图2-tcp拥塞控制策略

  如图2所示,发送方和接收方在建立tcp连接时,慢开始算法启动,设置拥塞窗口cwnd初始值为300字节,门限值ssthresh为1000。假设当cwnd增大到600时,发送方发送报文出现了超时(网络可能出现拥塞),此时乘法减小算法就会生效,更新门限值ssthresh为300(设置为拥塞窗口cwnd的一半),拥塞窗口再重新设置为300,并执行慢开始算法。

  假设此时,发送方发送报文没有超时(网络没有出现拥塞),但是cwnd值增大为1200,而门限值ssthresh为1000,此时cwnd大于ssthresh,因此这时,就会停止慢开始算法,启动拥塞避免算法。

  如果在拥塞避免阶段,发送方发送报文超时了,乘法减小算法同样会启动,如果没有超时,则增大算法生效,即让拥塞窗口缓慢增大。

  上面介绍的加法增大和乘法减小这两种算法经常合起来称为AIMD(加法增大乘法减小)算法。另外,这里再强调下,拥塞避免是指在拥塞避免阶段将拥塞窗口控制为按线性规律增长,即放慢增长速率,使网络不容易出现拥塞。


   另外,通过对比拥塞避免算法和慢开始算法中的拥塞窗口增长策略可以发现:拥塞避免算法的cwnd增长是基于往返时间RTT的,增长速率是按拥塞避免算法——加法增大,而慢启动算法中的cwnd增长是基于收到的ACK确认数量(即累积确认),增长速率是确认收到的mss。