【TCP】拥塞控制
出现拥塞
拥塞控制是防止过多的数据注入到网络中,使网络中的路由器或链路不过载,这是一个全局性的。
流量控制是点对点的通信量的控制,是端到端问题。
拥塞控制方法
在最宽泛的级别上,我们可根据网络层是否为运输(传输)层拥塞控制提供显示帮助,来区分拥塞控制方法。
端到端拥塞控制
在这种方式中,网络层没有为运输层拥塞控制提供显示支持。端系统必须通过对网络行为的观察(如分组丢失与时延)来推断网络是否出现拥塞。TCP必须通过端到端的方法来解决也拥塞控制,因为IP层不会向端系统提供有关网络拥塞的反馈信息。TCP报文段的丢失(通过超时或3次冗余确认得知)被认为是网络出现拥塞的一个迹象,TCP会相应地减小其窗口长度。
在TCP拥塞控制的一些最新建议也会使用往返时延RTT值的增加作为网络拥塞程度增加的指示。
网络辅助的拥塞控制
在网络辅助的拥塞控制中,网络层构件(即路由器)向发送方提供有关网络中拥塞状态的显示反馈信息。
拥塞信息从网络反馈到发送方通常有两种方式:
- 直接反馈信息由网络路由器发给发送方,这种通知方式常采用了一种阻塞分组(choke packet)的形式(含义为:“我阻塞了”)
- 显示拥塞通知(Explicit Congestion Notification,ECN)。该方式由路由器标记或更新发送方流向接收方的分组中的某个字段(IP头部的CE字段)来指示拥塞的产生。当接收方接收到这样的分组后,就会向发送方发送网络拥塞的通知(在回复的ACK的TCP字段置位ECN字段)。然而,这种方式需要至少需要一个完整的RTT。(使用网络辅助的拥塞控制例子可参见ATM ABR拥塞控制)
关于TCP拥塞控制的三个问题
TCP使用的是端到端拥塞控制。TCP所采用的方法是让每一个发送方根据感受到的网络拥塞程度来限制其能向其连接发送流量的速率。由此可引出三个问题:①TCP发送方如何限制它向其连接发送流量的速率?②TCP发送方如何感知它到目的地之间的路径上出现了拥塞?③当发送方感受到了端到端的时延,使用何种算法来改变其发送速率呢?下面我们一一分析。
TCP发送方如何限制它向其连接发送流量的速率?
一条TCP连接会建立一些状态变量,比如LastByteRead、rwnd。运行在发送方的TCP拥塞控制即使会跟踪一个变量,即拥塞窗口(congestion window)。拥塞窗口表示为cwnd,它对一个TCP发送方能向网络中发送流量的速率进行了限制。需要注意在一个发送方中未被确认的数据量不会超过cwnd和rwnd中的最小值。即:
为了关注拥塞控制(与流量控制形成对比),我们后面假设TCP接收缓存足够大,以至于忽略接受窗口rwnd的限制,发送方中未确认的数据量仅受限于cwnd。并且假设发送一直有数据要发送,即在拥塞窗口中的所有报文段都要被发送。
这些约束限制了发送方中未被确认的数据量,因此间接地限制了发送方的发送速率。
TCP发送方如何感知它到目的地之间的路径上出现了拥塞?
当过度的拥塞出现时,在沿着这条路径上的一台或者多台路由器的缓存会溢出,引起一个数据报(含TCP报文段)被丢弃。丢弃的数据报会引起发送方的丢包事件(超时或者受到三个冗余ACK),发送方就会认为到接收方的路径上出现了拥塞指示。(收到3个冗余ACK时,会进行快重传对丢失报文进行重传而不必等到超时再重传,因为超时重传对发送速率影响很大,二者对拥塞控制的影响可见下文。前一篇文章简要介绍了快速重传,后面会补充快重传为什么是要接收到3个冗余ACK)
TCP发送方如何确定它的发送速率?
发送方会接收到确认报文并且增加拥塞窗口长度,TCP可以被称为是自计时(self-clocking)的。给定cwnd来控制发送速率可还是不知发送方如何确定它应当发送的速率。如果众多发送方总体上发送地太快,它们会拥塞网络,而发送地太慢又不可以充分利用网络带宽。
那TCP是如何确定它们的发送速率,既不会使网络拥塞也不会浪费带宽?TCP发送方式显示地协作,或者存在一种分布式方法使得TCP发送方能够基于本地信息设置它们的发送速率?
这里有一些指导性原则回答这些问题:
-
一个丢失的报文段意味着拥塞,因此当丢失报文段时应当降低TCP发送方的速率
-
对当前未确认的报文的确认到达时,能够增加发送方的速率
确认报文的到达可以看做一些顺利的指示,指示发送方报文段被顺利地交付给接收方,网络中没有出现拥塞。因此,拥塞窗口长度可增加。
-
带宽探测
ACK报文回复隐含地指示了从源到目的地的路径上面没有出现拥塞,丢包事件则指示出现了拥塞。由此,TCP便通过调节其传输速率增加影响ACK报文,如果出现丢包便减小传输速率,然后再进行增加速率,看拥塞状况是否改变。
TCP拥塞控制算法
该算法主要包括3个主要部分:①慢启动;②拥塞避免;③快速恢复。慢启动和拥塞避免是TCP强制部分,两者的差异在于对接收到的ACK做出反应时cwnd增加的长度。慢启动比拥塞避免能更快的增加cwnd的长度。快速恢复是推荐部分,对TCP发送方并非是必需。
慢启动
在慢启动状态,cwnd的值以一个MSS开始并当传输的报文首次被确认就增加一个MSS。如下图所示,开始发送一个报文段,收到确认后拥塞窗口增加1。然后传输2个报文段,收到2个确认后增加拥塞窗口变成了4个MSS。这样没经过一个RTT,发送速率就会翻番。于是,TCP发送的起始速率慢,但是在慢启动阶段会以指数增长。
但是这样会的增长何时终止呢?慢启动对这个问题提供了几种答案。
-
第一种: 如果出现一个有超时引起的丢包事件(即网络中出现了拥塞),TCP发送方将cwnd设置为1并重新开始慢启动过程。它还会将第二个状态变量ssthresh(“慢启动阈值”)设置为cwnd/2。
-
第二种: 与ssthresh相关。当增加到cwnd=ssthresh时,结束慢启动并开始拥塞避免。
-
第三种: 如果检测到3个冗余ACK,这时TCP执行快速重传进入快速恢复状态。
拥塞避免
进入拥塞状态后,TCP的cwnd增加速率就比较缓慢,一个RTT将cwnd的值增加一个MSS,线性增长。例如,发送方在1个RTT时间内发送10个报文,那么收到所有10个确认报文后,拥塞窗口的值增加一个MSS。
在这个阶段的cwnd增长停止时的情况:
-
超时
出现超时,\(ssthresh = 1/2 * cwnd\),cwnd被置为1个MSS,然后开始慢启动
-
收到三个冗余ACK
TCP对于这种丢包事件,较与超时的做出的反应,比较温和。TCP将cwnd减半(为使测量结果较好,计已收到的3个冗余ACK要加上3个MSS),并将ssthresh置为cwnd(未减半)的一半。然后进入快速恢复状态。
快速恢复
在快速恢复中,对于引起TCP进入快速恢复状态的缺失报文段,对收到的每个冗余的ACK,cwnd的值都增加一个MSS。最终,当对丢失报文段的一个ACK到达时,TCP在降低cwnd后进入拥塞避免状态。如果出现超时事件:cwnd置为1个MSS,并且ssthresh置为cwnd的一半,迁移到慢启动。
快速恢复是TCP推荐部件而不是必需。一种早期的TCP版本TCP Tahoe,不管是超时而引起的丢包还是3个冗余ACK引起的丢包事件,都会将cwnd置为1个MSS,并进入慢启动阶段。TCP较新的版本TCP Reno综合了快速恢复算法。
附图一张TCP拥塞控制流程图
在每个RTT内cwnd线性增加1MSS,然后出现3个冗余ACK事件时cwnd减半(乘性减)。所以,TCP拥塞控制常被称为加性增乘性减(Additive-Increase, Multiplicative-Decrease, AIMD)拥塞控制方式。
基于迟延的拥塞控制算法之TCP Vegas算法
TCP Vegas算法试图在维持较好吞吐量的同是避免拥塞。基本思想是:①在分组丢失发生之前,在源与目的地之间检测路由器中的拥塞;②当检测出快发生分组丢失时,线性地降低发送速率。通过观察RTT来预测分组是否要发生丢失。分组的RTT越长,路由器中的拥塞越严重。
快速重传为什么是收到3次冗余ACK
对同一报文收到两次ACK很有可能是报文段乱序造成的,收到3个及3个以上一定是丢包造成的!
依据经验,收到3个duplicated ACK便可以启动快重传。
参考[知乎:TCP快速重传为什么是三次冗余ack,这个三次是怎么定下来的?车小胖回答
](https://www.zhihu.com/question/21789252)后,作图如下: