TCP拥塞控制:数据包守恒、慢启动、拥塞避免、快重传

5,525 阅读5分钟

TCP拥塞控制的起源

1986年,从LBL到UC Berkeley的网络吞吐因为拥塞出现了从32Kbps到40bps的急剧下降,Van Jacobson 在1988年的论文《Congestion Avoidance and Control》从这个问题出发,提出了数据包守恒定律以及慢启动、拥塞控制和快重传的算法,在1990年又提出了快恢复算法。

数据包守恒原则

在一个运行平稳的TCP连接中流动的数据包应该是守恒的,意思是当只有旧的数据包被成功传输到对端后,新的数据包才能加入到连接中。在TCP协议中,我们可以使用ack来作为判断数据包是否已经成功到达对端的依据,就是说当发送端收到good ack(大于发送端当前已经收到的最大ack的ack)时,它就可以发送新的数据包了。这种根据ack来决定继续发送数据包的机制就叫做self clocking(也叫做ack clocking)。

慢启动

通过数据包守恒原则,我们知道可以通过ack来决定是否发送新的数据,而要收到ack就要先发送数据。慢启动就开始发送数据时的行为控制。慢启动的总体思路就是从一个很低的初始值开始,逐渐增加数据发送的速度,直到达到超时或者丢包为止。慢启动的实现思路如下:

  1. 每个连接维护一个变量cwnd(congestion window)
  2. 当连接刚建立或者遇到丢包时,将cwnd设置为1,单位为MSS(maximum segment size)
  3. 每收到一个新的ack,cwnd加一
  4. 当发送数据时,能够发送的数据包数量为min(cwnd,awnd),awnd为接收端的滑动窗口大小(reciver's advertised window)

可以预见,在没有出现超时或者丢包时,慢启动增长的速度是指数级的,所以慢启动实际上并没有那么“慢”,“慢”是慢在它的起点只有1个MSS。

拥塞避免

前面提到,慢启动的目的是逐渐增加发送速度进行试探,直到出现网络拥塞,而真正出现拥塞时又该怎么做呢,就是“拥塞避免”所做的事情了。拥塞避免主要由两部分组成:

  1. 一个判断当前网路出现拥塞的机制
  2. 在出现拥塞时降低发送速度的机制

而拥塞避免的实现思路如下:

  1. 当出现超时时,将cwnd设置为当前值的一半(即当出现超时时就认为是出现了拥塞)
  2. 每收到一个新的ack,cwnd加1/cwnd(即当传输成功cwnd个数据包时,窗口大小加一,也就是随着RTT线性增加)

这里的两个变更cwnd的行为通常称为“乘法减小”和“加法增大”。

结合慢启动和拥塞避免的算法

值得注意的是,慢启动和拥塞避免实际上是两个不同的算法,它们一个用于试探网络资源的上限,另一个用于资源使用率达到或者接近上限时的行为。在1988年的论文中给出了一个结合了慢启动和拥塞避免的算法,具体实现思路如下:

  1. 发送端维持两个变量:拥塞窗口cwnd(congestion window)和慢启动门限ssthresh(slow start threshold),通过这两个变量来决定当前应该执行慢启动还是拥塞避免算法。
  2. 发送数据时,能够发送的数据包数量为min(cwnd,awnd)
  3. 出现超时时,ssthresh更新为cwnd/2(但不能小于2),cwnd设置为1
  4. 每收到一个新的zck,发送端的行为是:
    • 如果cwnd<ssthreshcwnd+=1(慢启动阶段,窗口指数级别增加)
    • 否则cwnd+=1/cwdn(拥塞避免阶段,窗口线性增加)

快重传

快速重传的目的就是让发送端尽快感知到丢包。TCP发送方在每发送一个分段时会启动一个计时器,如果相应的数据包确认没在特定时间内被送回,发送方就假设这个分段在网络上丢失了,需要重发。这也是TCP用来估计RTT的测量方法。

重复确认

重复确认基于以下过程:如果接收方接收到一个数据分段,就会将该分段的序列号加上数据字节长的值,作为分段确认的确认号,发送回发送方,表示期望发送方发送下一个序列号的分段。但是如果接收方提前收到更大的序列号的分段,或者说接收到无序到达的分段,接收方需要立即使用之前的确认号发送分段确认。此时如果发送方收到接收方相同确认号的分段确认超过1次,并且该对应序列号的分段超时计时器仍没超时的话,则这就是出现重复确认,需要进入快速重传。

快送重传就是基于以下机制:如果假设重复阈值为3,当发送方收到4次相同确认号的分段确认(第1次收到确认期望序列号,加3次重复的期望序列号确认)时,则可以认为继续发送更高序列号的分段将会被接受方丢弃,而且会无法有序送达。发送方应该忽略超时计时器的等待重发,立即重发重复分段确认中确认号对应序列号的分段。

TCP拥塞控制的各个实现

这里先列举各个TCP拥塞控制的实现,具体接受后续再补上了。

  • TCP Tahoe/Reno,Reno中首次增加了“快恢复”阶段
  • TCP Vegas
  • TCP New Reno
  • TCP BIC/CUBIC
  • TCP Westwood/Westwood+
  • Compound TCP
  • TCP PRR
  • TCP BBR