盈盈一水间
脉脉不得语
春招实习的时候,经过几次面试,发现这里都讲的不是很好,打算用心好好整一下。
为什么会有拥塞控制
如果说把网络链路比喻成一根水管,于是传输数据就成了给水管注水。
所以对应网络上能存在的数据量:
网络上能容量的数据包的数量(水管容量) = 链路带宽(水管截面积) x 往返延迟(水管长度)
这样存在的问题就是水的流量太大的时候,会发生爆管(本来设计水的流量是10立方米/分钟,因为管子太小,变成了1立方米/分钟),会导致所有水到达目的地的速度明显变慢,每单位体积的水在水管里停留的时间越长。
对应在网络中就是一个数据包收到回复确认的时间变长,于是数据包在网络链路里存在的时间也就越长,导致网络延迟高,丢包率变高。这个时候发送方会进行超时重传,于是网络状况就会越来越差。
为了解决这个问题,就出现了拥塞控制,控制水管的输入,也就是整体控制每个发送方的发送的速度,减少丢包率,相当于控制每个人发送的窗口大小。
TCP拥塞控制算法
主要讲Linux内核默认的Reno,然后顺带提一下Google的BBR。
Reno算法
Reno出现在几乎所有的计算机网络教材中,估计很多同学也已经忘了(包括我)。。。
其对拥塞的控制主要分为4个阶段:
- 慢启动
- 拥塞避免
- 快重传
- 快恢复
这里盗个图给帮助说明一下。
同样有对应的几个概念值:
- 拥塞窗口(cwnd),这个其实和流量控制的窗口类似,都用来表示一次能发出去的数据量。这个值随时间变化,变化速度在慢启动和拥塞避免阶段不一样。其变化范围,由是否发生丢包来决定,发生丢包,值就会变成原来的一半。
- 慢启动阈值(ssthresh),这是一个随丢包情况变化的值,用来作为慢启动和拥塞避免两个阶段的分界线。其第一次赋值是第一次发生丢包时,拥塞窗口(cwnd)值的一半。
慢启动阶段
慢启动意思就是拥塞窗口(cwnd)从最小值1开始变大。
而是将发送窗口的大小在初始的情况下设置为1,在收到接收方确认后,再修改其发送窗口为原来的两倍,也就是2。这样子的话,就是指数增长。
叫慢启动的原因估计就是发因为发送窗口是从1开始增长的,与后面的快恢复形成对比。
一般在慢启动阶段,碰到第一次丢包的时候会将慢启动阈值(ssthresh)设为当前窗口大小值的一半。
而慢启动到拥塞避免的分界线就是慢启动阈值(ssthresh)。
慢启动阶段
在慢启动阶段达到阈值(ssthresh)后就会进入拥塞避免阶段,拥塞避免阶段窗口的增长是线性的,。
这个阶段会持续到发生下一次丢包(超时)。如果发生了超时(TO),就会将阈值(ssthresh)设置为当前窗口的一半,然后窗口大小从1重新开始慢启动算法(慢恢复)。
快重传
快重传一定发生在乱序接收的情况下,A给B一次发送了[3, 4, 5, 6]
个包,假设此时5发生了丢包,这个时候B确认回复了3和4,也就是A收到了 [ACK(4), ACK(5), ACK(5)]
。A会继续发送[7, 8, 9, 10]
,此时A收到的确认就是 [ACK(5), ACK(5), ACK(5), ACK(5)]
,收到了3次或以上的重复确认,此时A就会直到5号数据包丢包,不等5号的计时器超时,便直接重传5号数据包,这就是TCP快速重传。
快恢复
快恢复算法是和快重传配合使用的算法,一般发生了快重传的时候,发送方能收到三次连续重复确认,说明此时网络并不是拥塞,只是单纯的丢包。此时会将阈值(ssthresh)设置为当前窗口的一半,然后窗口大小从阈值(ssthresh)重新开始拥塞避免算法(快恢复)。
这里与前面发生丢包后的慢恢复形成对比。其实也是Reno算法和Tahoe算法的一个区别,Tahoe算法是没有快恢复的。
BBR算法
太复杂了,再说吧。