TCP系列40—拥塞控制—3、慢启动和拥塞避免概述
本篇中先介绍一下慢启动和拥塞避免的大概过程,下一篇中将会给出多个linux下reno拥塞控制算法的wireshark示例,并详细解释慢启动和拥塞避免的过程。
一、慢启动(slow start)
一个TCP连接启动的时候并不知道cwnd应该取多大的值适合当前的网络状况,因此TCP发送方会从一个较小的初始值指数抬升cwnd到某一个值,这个cwnd抬升的过程就叫做慢启动。除了初始建立tcp连接(SYN包交换后)后的数据发送使用慢启动外,在TCP超时重传、TCP空闲一段时间后重新开始数据发送这些场景下也会触发慢启动过程。
在TCP连接的慢启动过程中,cwnd的初始值为IW(initial window)。IW的原始值为1个SMSS的大小,但是RCF5681协议允许IW按照如下设置(RFC3390中也有详细的设置原则描述和讨论)
SMSS>2190bytes时,IW=2*SMSS 且最大不能超过2个报文段
2190bytes>=SMSS>1095bytes时,IW=3*SMSS 且最大不能超过3个报文段
其他场景下,IW=4*SMSS 且最大不能超过4个报文段
为了接下来描述方便,我们取cwnd=IW=1*SMSS。其中SMSS一般为min(接收方的MSS,扣除header的path MTU)。假设没有丢包发生并且接收方每接收一个包就反馈一个ACK,则每当发送方接收到一个Good ACK的时候,发送方就会调整cwnd=cwnd+min(N,SMSS),其中N表示这个Good ACK反馈确认的接收方新收到的数据量,单位为byte。比如之前收到的最大ACK Number为1000,新收到的Good ACK中ACK Number为2000,则这个Good ACK指示接收方新收到了1000byte的数据,这种场景下N=1000bytes。当发送端以SMSS大小发送数据报文,接收方对每个报文都立即回复ACK的时候,简洁的整理以下算法流程如下
1)连接建好的开始先初始化cwnd = 1,表明可以传一个SMSS大小的数据。
2)每当收到一个ACK,cwnd++; 呈线性上升
3)每当过了一个RTT,cwnd = cwnd*2; 呈指数让升
4)还有一个慢启动门限ssthresh(slow start threshold),是一个上限,当cwnd >= ssthresh时,就会进入拥塞避免。
5)当遇到RTO超时重传时会触发cwnd和ssthresh的调整,ssthresh=max(cwnd/2, 2),cwnd=1,然后重新开始慢启动过程。
连接初始建立场景下可以设置ssthresh为一个很大的值,然后开始慢启动流程后,直到发送速率一直增大,最终触发RTO超时或者快速重传,然后根据cwnd设置ssthresh从而得到一个有效的ssthresh值。这里我们暂时只考虑RTO超时场景,后面会介绍快速重传、ECN等场景下的处理。
慢启动流程示意图如下

从上图可以看到每过一个RTT,cwnd就会增加一倍,因此TCP的慢启动是指数增长的(慢启动的"慢"是指TCP的发送端不能直接以接收方通告的awnd为窗口进行发送,而要有一个启动过程,因此叫做慢启动)。当发送端使用delay ACK时,慢启动的cwnd仍然是指数增长的,但是增长速度会稍微慢一些。因此有一些TCP实现会等TCP连接完成慢启动过程后在使用delay ACK,例如linux中在连接初始建立时候的quick ACK模式。
二、拥塞避免(congestion avoidance)
从慢启动可以看到,cwnd可以很快的增长上来,从而最大程度利用网络带宽资源,但是cwnd不能一直这样无限增长下去,一定需要某个限制。TCP使 用了一个叫慢启动门限(ssthresh)的变量,当cwnd超过该值后,慢启动过程结束,进入拥塞避免阶段。慢启动门限 ssthresh 的用法如下:
当 cwnd < ssthresh 时,使用慢开始算法。
当 cwnd > ssthresh 时,停止使用慢开始算法而改用拥塞避免算法。
当 cwnd = ssthresh 时,既可使用慢开始算法,也可使用拥塞避免算法。
拥塞避免算法的思路是让拥塞窗口 cwnd 缓慢地增大,假设cwnd=k*SMSS,当发送端收到一个包的ACK反馈的时候,按照cwnd=cwnd+(1/k)*SMSS。这样每经过一个RTT发送k个数据包的时候,cwnd增长了大约一个SMSS,通常上我们即描述为每经过一个往返时间 RTT 就把发送方的拥塞窗口 cwnd 加 1,使拥塞窗口 cwnd 按接近线性规律缓慢增长。这种增长方式叫做“加法增大”(Additive Increase)。另外当接收方使用delay ACK时,cwnd的增长仍然是接近线性的,只不过增长速度相对慢一些。总结如下
1)收到一个ACK时,cwnd = cwnd + 1/cwnd
2)当每过一个RTT时,cwnd = cwnd + 1
简单图示如下

无论在慢开始阶段还是在拥塞避免阶段,在Tahoe版本中,只要发送方判断网络出现拥塞(其根据就是触发了快速重传或者RTO重传),就要更新慢开始门限 ssthresh =max(flight size/2,2*SMSS),因为一般情况下flight size接近或者等于cwnd,所以也可以认为更新ssthresh =max(cwnd/2,2*SMSS),这个过程叫做“乘法减小”(Multiplicative Decrease)。加法增大与乘法减小常常合称为AIMD算法。另外,Windows中的实现据传为ssthresh =max(min(cwnd, awnd)/2, 2*SMSS) 。总结如下
- sshthresh = max(cwnd/2,2*SMSS) (一般来说当发生丢包的时候 cwnd一般都是大于等于4的,所以也可以认为ssthresh =max(cwnd/2,2*SMSS)=cwnd/2)
- cwnd 重置为 1
- 进入慢启动过程
三、拥塞控制示例
上面所讲解的慢启动和拥塞避免就是Tahoe版本的TCP实现,这个也是带有拥塞控制功能的第一个TCP版本,随着4.2 BSD UNIX一起发布。同时Tahoe版本是支持快速重传的,但是Tahoe版本对于快速重传和RTO重传的处理是一致(Reno版本的TCP对于快速重传和RTO重传的处理略有不同,接下来的拥塞控制系列会讲解)。
下面我们看一个图解示例以加深理解,下图中横坐标以RTT为单位,纵坐标cwnd用报文段为单位(可以看成SMSS大小为单位),我们假设接收端通告的窗口足够大,只考虑cwnd的变化。

分别对图中标示的箭头做如下说明
1、在标号为1的箭头处,TCP初始连接进行数据交换,开始慢启动,初始cwnd=IW=1,ssthresh=16,在传输轮次0-4阶段进行慢启动过程,cwnd按照1-2-4-8-16的顺序进行指数增长
2、在标号为2的箭头处,cwnd=16=ssthresh,此时触发拥塞避免过程,开始线性增长,在传输轮次4-12阶段,cwnd按照16-17-18-19-20-21-22-23-24进行线性增长。
3、在标号为3的箭头处,TCP发生了RTO重传,认为网络发生拥塞,于是设置ssthresh=cwnd/2=12,cwnd=1重新进行慢启动过程
4、在标号为4的箭头处,TCP从cwnd=1开始重新开始慢启动过程
5、在标号为5的箭头处,当 cwnd = 12 时改为执行拥塞避免算法,拥塞窗口按按线性规律增长,每经过一个往返时延就增加一个 MSS 的大小。
附件列表
TCP系列40—拥塞控制—3、慢启动和拥塞避免概述的更多相关文章
- TCP系列41—拥塞控制—4、Linux中的慢启动和拥塞避免(一)
一.Linux中的慢启动和拥塞避免 Linux中采用了Google论文的建议把IW初始化成了10了.在linux中一般有三种场景会触发慢启动过程 1.连接初始建立发送数据的时候,此时cwnd初始化为1 ...
- TCP系列54—拥塞控制—17、AQM及ECN
一.概述 ECN的相关内容是在RFC3168中定义的,这里我简单描述一下RFC3168涉及的主要内容. 1.AQM和RED 目前TCP中多数的拥塞控制算法都是通过缓慢增加拥塞窗口直到检测到丢包来进行慢 ...
- TCP系列44—拥塞控制—7、SACK关闭的快速恢复
) return; delta = ssthresh - in_flight; prr_delivered += newly_acked_sacked; if (delta < 0 ...
- TCP系列43—拥塞控制—6、Congestion Window Validation(CWV)
一.概述 在RFC2861中,区分了TCP连接数据传输的三种状态 After sending a data segment: If tcpnow - T_last >= RTO ...
- TCP系列39—拥塞控制—2、拥塞相关算法及基础知识
一.拥塞控制的相关算法 早期的TCP协议只有基于窗口的流控(flow control)机制而没有拥塞控制机制,因而易导致网络拥塞.1988年Jacobson针对TCP在网络拥塞控制方面的不足,提出了& ...
- TCP系列55—拥塞控制—18、其他拥塞控制算法及相关内容概述
前面我们演示分析了100+个wireshark TCP实例,拥塞控制部分也介绍常见的拥塞处理场景以及4种拥塞撤销机制,但是我们一直使用的都是reno拥塞控制算法.实际上拥塞控制发展到今天已经有了各种各 ...
- TCP系列42—拥塞控制—5、Linux中的慢启动和拥塞避免(二)
在本篇中我们继续上一篇文章wireshark的示例讲解,上一篇介绍了一个综合示例后,本篇介绍一些简单的示例,在读本篇前建议先把上一篇读完,为了节省篇幅,本篇只针对一些特殊的场景点报文进行讲解,不会像上 ...
- TCP系列51—拥塞控制—14、TLP、ER与拥塞控制
一.概述 这里的重点是介绍TLP.ER与拥塞控制并不是介绍TLP和ER本身,因此TLP和ER的详细内容请翻前文. 在TLP与拥塞控制的交互中有几个点需要注意 1.TLP触发的重传后,TCP仍然处于Op ...
- TCP系列48—拥塞控制—11、FRTO拥塞撤销
一.概述 FRTO虚假超时重传检测我们之前重传章节的文章已经介绍过了,这里不再重复介绍,针对后面的示例在说明两点 1.FRTO只能用于虚假超时重传的探测,不能用于虚假快速重传的探测. 2.延迟ER重传 ...
随机推荐
- spring-构建mvc工程
SpringMVC基于模型-视图-控制器(MVC)模式实现,可以构建松耦合的web应用程序. 1.SpringMVC的请求过程 1)请求离开浏览器,并携带用户所请求的内容 2)DispatcherSe ...
- 在 Ubuntu Linux 14.04 LTS 上安装php7
首先添加php官方源 $ sudo add-apt-repository ppa:ondrej/php 然后更新源 $ sudo apt-get update 然后安装 $ sudo apt-get ...
- Tensorflow取消占用全部GPU
参考:https://www.cnblogs.com/jiu0821/p/9501665.html Tensorflow默认是会占用全部的GPU,而有时候你根本不需要那么占用那么多GPU资源,这时候就 ...
- Scratch入门课程(1)——把工具准备好
为了让更多的同学了解少儿编程,从今天开始,我将以每周1次的频率发布Scratch的入门课程,大约在30课时左右. 几点情况说明: 1.这批课程主要面向2-4年级的同学,难度都不大,按照教程可以很轻松地 ...
- LeetCode:40. Combination Sum II(Medium)
1. 原题链接 https://leetcode.com/problems/combination-sum-ii/description/ 2. 题目要求 给定一个整型数组candidates[ ]和 ...
- Linux tcpdump命令详解(分享文章)
简介 用简单的话来定义tcpdump,就是:dump the traffic on a network,根据使用者的定义对网络上的数据包进行截获的包分析工具. tcpdump可以将网络中传送的数据包的 ...
- HashMap在并发场景下踩过的坑
本文来自网易云社区 作者:张伟 关于HashMap在并发场景下的问题有很多人,很多公司遇到过!也很多人总结过,我们很多时候都认为这样都坑距离自己很远,自己一定不会掉入这样都坑.可是我们随时都有就遇到了 ...
- VueJs 学习笔记
VueJs学习笔记 参考资料:https://cn.vuejs.org/ 特效库:TweenJS(补间动画库) VelocityJS(轻量级JS动画库) Animate.css(CSS预设动画库) ...
- 【springboot-01】整合quartz
1.什么是quartz? quartz是一个开源的定时任务框架,具备将定时任务持久化至数据库以及分布式环境下多节点调度的能力.当当的elastic-job便是以quartz为基础,结合zookeepe ...
- React中类定义组件constructor 和super
刚开始学习React没多久,在老师的教程里看到了类组件的使用示例,但是和资料上有些冲突,而引发了一些疑问: 类组件中到底要不要定义构造函数constructor()? super()里边到底要不要传入 ...