day9:拥塞控制

拥塞控制相当于将端到端的flow control的范围扩展到整个网络


目的:
1.如何尽可能减少拥塞的出现?
2.如何分摊网络负担?

前言

拥塞的产生:

以一个交换机为例,在没有任何拥塞控制的机制下,如果它的输出数据速率小于输入总容量,就会产生拥塞。而且,拥塞发生后,发送的分组(packet)没有被成功接收,于是发送方就会重传,这样进一步加剧了拥塞。

使用分组交换,拥塞的出现是不可避免的,交换机中的缓冲区总是不可避免地被等待的分组占用。但换个角度想,如果缓冲区长时间都是空着的,虽然排队延迟很低,但这也意味着利用率很低。缓冲区长时间都被占用着,虽然排队延迟高了,但网络利用率同样变高了。所以拥塞控制的核心想法是:可以有拥塞,但我们要控制拥塞的程度。

公平分配

之前提到过,如果有多个输入方发送数据,输出数据速率将会分配给不同输入方使用。如果将输出数据速率均分给所有输入方,显然这不是公平:输入方的数据速率肯定有大有小,如果给小的分多了,对于大的一方肯定不公平。
怎样分摊网络负担才算公平?从最大化吞吐量的角度,和从流量瓶颈的角度出发,会得出相互矛盾的结果。公平分配的其中一种方法是:max-min fair share

max-min fair share算法:
首先假定用户集合有n个用户,1到n,他们对资源的需求已经排序完毕,满足s1<s2< … <sn,资源总量为S。
1、将资源S/n分配给需求最小的1用户,这很可能已经超出了用户1的需求; 2、将超出的部分回收,再次将(S-s1)/(n-1)的资源分配给用户
2,依次次重复上述过程,直到某一次分给该用户的资源不满足该用户的需求;
3、假定当分配到第k个用户时,分配到的资源不能达到该用户的需求,那么就将剩下的资源,平均分配给未获得资源的所有用户,至此,分配任务结束。
这种算法的缺点是没有给发送方提供反馈。
————————————————————————————————————————————
举个例子,假如一个路由器的输出数据速率是1,有三个主机向路由器发送数据,数据速率分别是A:0.1、B:0.5、C:1.5、D:0.5。按照max-min fair share算法,路由器的输出数据速率应该这样分配:
1.数据速率从小到大排列:0.2,0.5,0.5、1.5
2.将输出数据速率先均分,暂时拟定每个人分配到的输出数据速率是0.25
3.按照“先分给小的,再分给大的”,分给A的输出数据速率是0.25,比A原本的数据速率要大,于是修改成:分给A的输出数据速率就是其原本的数据速率0.1
4.分到第二个人时,发现拟分配的数据速率0.25已经小于其原本的数据速率了,于是就将剩余未分配的输出数据速率0.9均摊给剩余的所有人,即B、C、D每个人都只得到输出数据速率0.3。

拥塞控制不能仅仅依靠路由器的公平分配来实现,因为公平分配机制不能解决【输出速率小于输入速率导致的数据包丢失的】问题,根本原因是它并没有给发送方提供反馈,从数据的来源——发送方解决问题。
我们需要一些反馈机制,让发送方调整数据速率。网络不去干,那就让终端去干。IP不去干,那拥塞控制的重任就落到了TCP的头上。

TCP拥塞控制

TCP的拥塞控制尝试找出它可以随时安全地在网络中处理多少个数据包,通过观察分组的丢失情况,判断是否出现了拥塞,进而控制sliding window的大小,减少发送量

怎么知道是网络拥塞而不是单纯的网络错误丢包?
——现在的网络传输质量都很好,丢包率都在1%以下,因此就默认“丢包了就是拥塞了”

拥塞控制的目的是:让发送的数据包尽可能多,但不能过多,要有限制,从而提升整体的网络质量
由于从网络内部所获得的信息有限,因此需要从信号的丢失情况来推断网络的拥塞情况。

TCP在发送分组时,要面临三大问题:
什么情况下发送新数据?——发送cwnd范围内的序列号对应的分组
什么情况下重传数据?——合理设置重传时间上限timeout
什么情况下发送ack?——收到data就回复,两者之间的延迟越小越好,self-clocking

发送新数据——cwnd

在这里插入图片描述
如何决定cwnd的值是多少?
TCP使用两种状态来实现拥塞控制(本质上是实现对cwnd大小的控制):slow start和congestion avoidance。
AIMD其实就是congestion avoidance,下面以AIMD的讲解代替congestion avoidance。

强烈建议结合sliding window的演示网址:
http://www.exa.unicen.edu.ar/catedras/comdat1/material/Filminas3_Practico3.swf

1.AIMD

例如:一开始发送seq1、seq2、seq3、seq4。收到ack1后,发送seq5。收到ack4后,发送8。而由于AIMD的机制,发送8以后,接下来不用傻等着收ack4,可以再发一个seq9,然后才等着收ack4。
cwnd的值不停地做以下调整:
如果上一轮总共cwnd个分组都被成功接收,则下一轮的cwnd=cwnd+1(cwnd的最大值为sliding window的最大尺寸N)
如果有一个分组半路丢失了,则cwnd=cwnd/2

可以容易推导,cwnd的变化间隔为一个RTT

对于single flow
cwnd的变化与RTT的变化是同步的,两者一起增加,一起变成一半。R=cwnd/RTT,R是吞吐量,由刚刚的推导得知,R的值总是不变的

为什么两者是同步变化的?
——两者步调一致,因为本质上它们是相同的。

因此,
cwnd(packet)=RTT×R
cwnd(bit)=RTT×C

吞吐量R(packet/s)、数据速率C(bit/s)的关系:R=C/每个包的位数(bit/packet)

在bottleneck link和buffer都满了的情况下,cwnd达到最大值,发送出去的数据buffer和bottleneck各占一半。下一时刻丢了一个包,立刻就变为原本的1/2。变为1/2后,输入数据大幅减少,buffer会腾出时间被清空,但bottleneck link还是保持满状态传输,发送出去的数据都在bottleneck link中。然后不停重复上述的【满->半->满】的过程。因此认为,AIMD的初始状态,就是buffer为空、bottleneck link为满。

利用ping指令得到的RTT是RTT最大值的1/2,cwnd也是其最大值的1/2,对应的是【bottleneck link满了,进入了AIMD状态,而路由器的buffer是空的】。当bottleneck link和buffer都满了,则RTT变为最大值,cwnd也变为最大值。
虽然说cwnd的变化间隔为RTT,但是此处RTT是变化的,因此在single flow时更经常这样问:cwnd发送了多少个包以后回到最大值?

对于multiple flow
RTT的值可以看做不变。因此R的值不再是不变的。不过每一个flow依然遵循single flow的计算公式
在这里插入图片描述

由该等式可以看到:
1.RTT越大,吞吐量R越小,这对远距离传输不友好
2.R对丢包率p的变化很敏感

2.slow start

AIMD是每隔RTT,cwnd才+1
而slow start是:每收到一个ack,cwnd就+1

例如:
0 × RTT:
一开始发送seq1,cwnd=1,可发送的序列=1。黄色代表已经发出去等ack的。
1 × RTT:
收到ack1后,cwnd=>2,可发送的序列=2、3。于是发送2、3
2 × RTT:
收到ack2后,cwnd=>3,可发送的序列=3、4、5。于是发送4、5
收到ack3后,cwnd=>4,可发送的序列=4、5、6、7。于是发送6、7
3 × RTT:
收到ack4后,cwnd=>5,可发送的序列=5、6、7、8、9。于是发送8、9
收到ack5后,cwnd=>6,可发送的序列=6、7、8、9、10、11。于是发送10、11
……

可以明显看到,slow start第k个RTT直到下一个RTT期间,总共发送了2k个包,cwnd最终变为2k

假设cwnd=4后就已经进入congestion control状态,于是:
3 × RTT:
收到ack4后,cwnd=4,可发送的序列=5、6、7、8,于是发送8
收到ack5后,cwnd=4,可发送的序列=6、7、8、9,于是发送9
收到ack6后,cwnd=4,可发送的序列=7、8、9、10,于是发送10
收到ack7后,cwnd=>5,可发送的序列=8、9、10、11、12,于是发送11、12

slow start的slow体现在哪?
——指数增长的slow start一点也不slow。一方面可以看成,slow是因为cwnd的起点值很低。另一方面,根本原因是:slow其实是和以前的TCP传输方法比起来慢了。以前的TCP传输是立刻把整个flow control窗的内容发送出去。

slow start的指数增长用于快速找到网络的容量。当接近网络的容量时,使用congestion avoidance来缓慢靠近容量值。
如何实现slow start到congestion avoidance的状态切换呢?

如果ack序列号不断增加,说明传输很顺利
如果收到了重复的ack序列号,说明中途有分组丢失
如果没有收到ack序列号,说明问题大了

什么叫重复的ack?
——from 知乎:
——相当于:收到3以后,只要以后收到的不是4,每收一次就回复一次ack4在这里插入图片描述

更直接地,我们使用了cwnd和另一个新的量:ssthresh(slow start threshold,慢启动阈值)。
下图是TCP tahoe时代的状态切换图
在这里插入图片描述

在RFC 5681官方文档中写到,当TCP发送方使用重传定时器检测到段丢失,而给定段尚未通过重传定时器重新部署时(即给定段之前没有重传过),必须将ssthresh的值设置为不超过方程式(4):

ssthresh=max(FlightSize/2,2*SMSS)……(4)

其中,FlightSize是网络中未完成的数据量。
另一方面,当TCP发送方使用重传定时器检测到段丢失,并且给定段已经通过重传定时器至少重传一次时,ssthresh的值保持不变。

3.fast-recovery,fast retransmit

可以看到上图,以前的TCP tahoe一旦timeout了,从congestion control切换到slow start时会直接将cwnd设成1。然而时代变了。现在的TCP reno修改了这一点规定,也就是fast recovery:从congestion control切换到slow start时,cwnd变为原来的一半
在这里插入图片描述

重传——RTT estimation

估计RTT很重要。合理估计RTT相当于设置合理的timeout。估计的值太小,会浪费容量在触发slow start和重传上(还没收到ack就急急忙忙重传);估计的值太大
但RTT是动态变化的,和网络负载有关
在这里插入图片描述
m:由最近收到的ack得到的RTT测量值
g:权重

r:RTT估计值。r=r+g×(m-r)
v:方差。v=v+g(|m-r|-v)
timeout=r+βv,β=4
这种是现在用的比较健壮的估计方法。好处是:m变化平稳时,timeout也相对平稳;当m急剧增大时,timeout也能跟上m变化的步伐。这样无论哪种情况,RTT估计值也很接近实际值,而且timeout值合适。

发送ack——self-clocking

只要一收到data,就尽快主动回复ack
只有发送了一次data以后,才跟着发送下一次data。否则的话会增加网络拥塞
收到ack后,就发送新的data作为对ack的回复

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值