TCP的拥塞控制方法,是批量数据传输中最重要的,拥塞控制用于防止网络因为大规模的通讯负载而瘫痪
当认为网络即将进入拥塞状态,或者已经因为拥塞而出现路由器丢包情况时候,降低TCP传输
路由器因无法处理高速率到达的流量而被迫丢弃数据信息的现象被称为拥塞,当路由器处于上述状态时,就出现了网络拥塞
ECN算法允许一个TCP发送端向网络报告拥塞状况,而不用检测丢包,但这要求网络中每个路由器都参与,实现度很难
目前的网络环境,没有一个明确的信号通知发送方已经出现拥塞
判断拥塞的方式
1.基于丢包,利用ACK和SACK报文探测,ECN算法(如果可用),重传计时器的超时来判断的
2.通过不断增长的RTT值作为拥塞形成信号来判断的
Vegas,FAST,TCP Westwood,Westwood+,复合TCP 都是基于RTT来判断的
TCP需要知道 什么时候减速,以及怎样减速,还有如何恢复传输速度
其实一共有四种方式,总结如下
TCP拥塞控制算法发展的过程中出现了如下几种不同的思路:
慢启动和拥塞控制
慢启动为发送方的TCP增加了一个窗口:拥塞窗口(congestion window),记做 cwnd
当与另一个网络的主机建立TCP连接时,拥塞窗口被初始化为1个报文段(即另一端通告的报文段大小)。每
收到一个ACK,拥塞窗口就增加一个报文段(cwnd以字节为单位,但是慢启动以报文段大小为单位进行增
加)。发送方取拥塞窗口与通告窗口中的最小值作为发送上限。
拥塞窗口是发送方使用的流量控制
滑动窗口是接收方使用的流量控制
慢启动的时间流逝图如下(使用指数增加的方式,慢慢的增加,如果网速很快,增长的也会很快)
拥塞避免算法和慢启动算法需要对每个连接维持两个变量: 一个拥塞窗口cwnd和一个慢启动门限ssthresh,这样得到的算法工作过程如下:
1.对一个给定的连接,初始化cwnd为1个报文段,ssthresh为65535个字节。
2.TCP输出列程的输出不能超过cwnd和接收方通告窗口的大小。
3.当拥塞发生时(超时或者受到重复确认),ssthresh被设置为当前窗口大小的一般(cwnd和接收方通告窗口大小的最小值,但最少为2个报文段)。此外如果是超时引起了拥塞,则cwnd被设置为1个报文段。
4.当新的数据被对方确认没增加cwnd,但增加的方法依赖于我们是否进行慢启动或拥塞避免。如果cwnd小于或等于ssthresh,则正在进行慢启动,否则正在进行拥塞避免。
对于慢启动的计算方式:
1.初始的cwnd=1,此时可以发送1个字节的MSS
2.每收到一个ACK,cwnd++,也就是线性增长
3.每经过一个RTT,也就是指数增长
4.当cwnd>=ssthresh时,就会进入 拥塞避免 算法
拥塞避免的计算方式:(慢启动阀值slow start threshold)
当cwnd>=ssthresh时,就进入拥塞避免状态
1.每收到一个ACK时,cwnd = cwnd + 1/cwnd
2.每过一个RTT时,cwnd = cwnd + 1
所以这是一个线性增长的算法
拥塞恢复算法:
1.设置sshthresh = cwnd /2
2.设置cwnd 重置为 1
3.进入慢启动过程
快速恢复算法:
1.设置cwnd = cwnd /2
2.设置sshthresh = cwnd
3.cwnd = sshthresh + 3 * MSS (3的意思是确认有3个数据包被收到了)
4.重传Duplicated ACKs指定的数据包
5.如果再收到 duplicated Acks,那么cwnd = cwnd +1
6.如果收到了新的Ack,那么,cwnd = sshthresh ,然后就进入了拥塞避免的算法了。
但是快速恢复算法依赖于三个重复的ACK,但是收到3个重复的ACK可能不止丢一个包可能就很多,而那些需要等到RTO超时才会重传
共享状态信息和友好性
TCP连接关闭后会将拥塞信息保存,之后的TCP连接会共享这些信息
TCP在传输路径中
Tahoe算法是TCP的早期版本,他的核心思想是让cwnd以指数方式迅速逼近可用信道容量,然后慢慢接近均衡
包括3个基本的拥塞控制算法:慢启动,拥塞避免,快速重传
Tahoe的缺点体现在快速重传后转向慢启动算法,这样导致效率比较低
Reno算法是针对Tahoe算法的不足做的改进只有两点
收到连续3个重复ACK后不经过慢启动,直接进入拥塞避免截断
增加了快速重传和快速恢复机制
Reno成为TCP源算法的主流
NewReno中快速恢复做了补充,Reno的缺点是对于以前慢速的网络效果很好,但现在高速网络中有延迟
Reno算法中规定发送方收到一个不重复的应答就退出快速恢复,而NewReno中,只有当所有报文分组都被应答了才退出快速恢复状态
SACK可以让发送方确定具体要重传哪些数据包
SACK TCP强调拥塞管理和选择重传机制分离,而传统的无SACK TP则将两者结合
FACK算法
SACK对于快速重传的3个重复ACK,好处是可以精确的定位到具体可以重传哪些数据
但是重传的数据包过多的话,又会对本来就有繁忙的网络造成负担
FACK用来做重传过程中的拥塞控制的
高速环境中的TCP拥塞算法
1.HSTCP,对基础算法修改,在高速环境中,针对更低的丢包率和更大的窗口,TCP响应函数做了相应了调整
慢启动做了调整,放缓了增长速度,这个算法兼顾了普通环境下与传统TCP的公平性,但在特殊环境中
能够达到更快的发送速度
2.BIC,使用两个算法来修改标准TCP发送端- 二分搜索增大,加法增大
二分搜索增大过程:
min_windows = 最近一次完整RTT中没有出现丢包的窗口大小
max_windows = 最近一次出现丢包时的窗口大小
def search():
new_windows = (min_windows, max_windows)
if(new_windows 不丢包):
min_windows = new_windows
else:
max_windws = new_windows
# end def
之后不断的迭代,这个算法拥有比标准TCP更快的速度,它是为充分利用高速网络没有不必要的延迟优点而设计的
它的增长速率在一些时间点是下降的,也就是越接近饱和点,它就增长的越慢,而大多数其他算法在接近饱和点时都会更快
当使用二分搜索增大算法时,可能出现当前窗口大小 与 中间点 之间的差距很大,由于可能出现突然大量数据注入网络的
情况,所以在一个RTT内将窗口增大到中间点可能并不是一个好方法,这时就采用加法增大算法
当中间点 与 当前窗口的差值 > 一个特定的阈值时,采用加法增大算法
3.Cubic,2.6.18内核之后的默认拥塞控制算法,改进了BIC在一些情况下增长过快的不足,并对窗口增长机制进行了简化
这个算法不像BIC 那样使用阈值 来决定何时调用加法增大算法/二分搜索增大算法, 而是使用一个高阶多项式函数,具体
来说是一个三次方式,来控制窗口的增大,三次方程的曲线既有凸的部分也有凹的部分,这就意味着,在一些部分(凹的部分)
增长的比较缓慢,在另一些部分(凸的部分)增长的比较迅速,在BIC和CUBIC算法之前,所有TCP研究提出的都是凸的窗口增长
函数,CUBIC算法中,这个特殊的窗口增长函数如下
W(t) = C(t-K)^3 + Wmax
W(t)代表在时刻t的窗口大小
C是一个常量(默认是0.4)
t是距离最近一次窗口减小所经过的时间,以秒为单位
K是在没有丢包的情况下窗口从W增长到Wmax 所用的时间
Wmax 是最后一次调整前的窗口大小
K 可以根据下面公式计算,其中beta 是积式减少的常量(默认为0.2)
CUBIC的窗口增长函数
Linux2.6.18内核版本起,CUBIC 是默认的拥塞控制算法,
从2.6.13内核开始,支持可装卸载的拥塞避免模块,用户可以选择想用的算法
//当前系统默认的拥塞控制算法
cat /proc/sys/net/ipv4/tcp_congestion_control
cubic
//用户允许应用程序使用的算法(可以使用具体选择或者设置为默认)
//默认支持 CUBIC算法 和 Reno算法
cat /proc/sys/net/ipv4/tcp_allowed_congestion_control
cubic reno
基于延迟的拥塞控制算法
1.Vegas,TCP协议发布后第一个基于延迟的拥塞控制方法,Vegas算法首先估算了一定时间内网络能够传输的
数据量,然后与实际传输能力进行比较,若本该传输的数据并没有被传输,那么它有可能被链路上的某个
路由器挂起,如果这种情况持续不断的发生,那么Vegas发送端将降低发送速率,这与标准TCP中利用丢包
来判断是否发生拥塞的方法相对
在拥塞避免阶段,Vegas算法测量了每个RTT中所传输的数据量,并将这个数除以网络中观察到的最小延迟时间,
算法维护了两个阈值a和b,吞吐量必须介于a和b之间,否则减小或增大拥塞窗口
这个算法只监控了发送端的延迟,但目标端返回的ACK也可能会延迟,但这个算法检测不到
2.FAST,原理上与Vegas算法相同,他根据预期的吞吐量和实际的吞吐量的不同来调整窗口,与Vegas
算法不同的是,它不仅依据窗口大小,还根据当前性能和预期的值的不同来调整窗口
3.Westwood,WestWood+是对Westwood的改进,这个算法对传统的NewReno改进,实现对大带宽延迟积链路的处理
类似Vegas算法(基于预期速率预实际速率的差别),该估计值被不断计算,但不同的是,这个速率的测量会有
一个测量间隔,该间隔基于ACK的到达动态可变,当拥塞不明显时测量间隔比较小,反之亦然
当检测到丢包时,根据带宽的值来估计拥塞窗口,慢启动的阈值
Some well-known congestion avoidance mechanisms are classified by this scheme as follows:
Variant | Feedback | Required changes | Benefits | Fairness |
---|---|---|---|---|
(New)Reno | Loss | - | - | Delay |
Vegas | Delay | Sender | Less loss | Proportional |
High Speed | Loss | Sender | High bandwidth | |
BIC | Loss | Sender | High bandwidth | |
CUBIC | Loss | Sender | High bandwidth | |
H-TCP | Loss | Sender | High bandwidth | |
FAST | Delay | Sender | High bandwidth | Proportional |
Compound TCP | Loss/Delay | Sender | High bandwidth | Proportional |
Westwood | Loss/Delay | Sender | L | |
Jersey | Loss/Delay | Sender | L | |
BBR[11] | Delay | Sender | BLVC, Bufferbloat | |
CLAMP | Multi-bit signal | Receiver, Routers | V | Max-min |
TFRC | Loss | Sender, Receiver | No Retransmission | Minimum delay |
XCP | Multi-bit signal | Sender, Receiver, Router | BLFC | Max-min |
VCP | 2-bit signal | Sender, Receiver, Router | BLF | Proportional |
MaxNet | Multi-bit signal | Sender, Receiver, Router | BLFSC | Max-min |
JetMax | Multi-bit signal | Sender, Receiver, Router | High bandwidth | Max-min |
RED | Loss | Router | Smaller delay | |
ECN | Single-bit signal | Sender, Receiver, Router | Less loss |
现在的网络设备中包含了大量的包缓冲区,TCP这样的协议会导致缓冲区膨胀
排队等待而产生的大量延迟,TCP的拥塞控制算法会在链路的瓶颈处将缓冲区填满,而拥塞的信号需要很长时间才能反馈到发送端,此时发送端和接收端之间缓存了大量数据,TCP协议也不能很好的运作
一些路由器支持ECN Explicit Congestion Notification 显示拥塞通知机制,对经过路由器的数据包进行标记(设置IP头中的两个ECN标志位),来通知拥塞状况
随机早期检测RED 网关机制能够探测拥塞情况的发生,并且控制数据包标记,这些网关实现了一种衡量平均占用时间的队列管理方法,控制占用时间在最大-最小范围之内,否则就丢弃数据包
参考
TCP的那些事儿(下)
在深谈TCP/IP三步握手&四步挥手原理及衍生问题
不为人知的网络编程(一):浅析TCP协议中的疑难杂症(上篇)
《高性能网络编程(一):单台服务器并发TCP连接数到底可以有多少》
《高性能网络编程(二):上一个10年,著名的C10K并发连接问题》
《高性能网络编程(三):下一个10年,是时候考虑C10M并发问题了》
《高性能网络编程(四):从C10K到C10M高性能网络应用的理论探索》
TCP congestion control
浅谈TCP拥塞控制算法
TCP拥塞控制算法比较