面试官:我说传统TCP的拥塞控制算法有问题,说说什么情况下他会误判?
前言
Hi 你好,我是东东拿铁,一个正在探索个人IP&副业的后端程序员。
都说TCP是一个靠谱的协议,流量控制、拥塞控制,已经深深的印刻在了程序员的脑海里,但他们具体的实现原理,不知道你又了解多少呢?
大家先试着回答几个问题吧
- TCP超时重试的时间,时间是怎么计算的?
- 丢包了,一定是网络满了吗,这时候认为拥塞会不会有问题?
- 诞生40多年的TCP拥塞控制算法,有没有优化空间?
- BBR是什么,解决了什么问题?
带着这几个问题,我们来一起看看今天的文章吧。
顺序、丢包问题
超时重试
TCP传输的数据,是被分割成小的数据包(segment)传输的,每一个数据包都有唯一id,下方统称为数据包。
举个例子,比如数据包5,接收方收到了,并发送了ACK,发送端未收到ACK。
发送端对于每一个发送出去的包,都有一个定时器。当过了一定时间,还没有收到ACK,就重新尝试。
那这个时间怎么定呢?在收到ACK前,数据需要经过一来一回,所以等待时间,必须大雨往返时间,否则会有不必要的重试。
估计往返时间,需要 TCP 通过采样 RTT(Round-Trip Time) 的时间,然后进行加权平均,算出一个值,而且这个值还是要不断变化的,因为网络状况不断的变化。除了采样 RTT,还要采样 RTT 的波动范围,计算出一个估计的超时时间。由于重传时间是不断变化的,我们称为自适应重传算法(Adaptive Retransmission Algorithm)。
那假设包5,在重试了一次之后,很不幸,又丢了,那又面临一次重传。
TCP会让超时时间加倍,每次超时重传,都会将等待时间翻倍。
快速重传
刚刚的超时触发重传,可能会耽误的时间较长,有什么别的办法吗,有,快速重传。
比如接收方收到数据包6、8、9,很容易看到就是7丢了,那么发送三个6的ACK,发送端不等超时时间,立刻重发7。
流量控制
两个应用程序通过TCP协议在网络中传输数据时,双方在硬件性能和软件性能上均可能存在差异,导致双方处理数据的速度不一致。当发送方的发送速度低于接收方接的处理速度时,不会出现问题。而当发送方的发送速度高于接收方的处理速度时,接收方会抛弃暂时无法“安置”的数据包。由于这些丢弃的数据包得不到确认,发送方会重新发送它们,直到他们被成功接收,造成资源浪费。TCP流量控制就是确保发送方的发送速度不要超出接收方的处理能力。
实现机制
发送方和接收方都维护着一个缓冲区来处理数据,也就是Buffer。
发送端:sender buffer
接收方:receiver buffer
上文说过,接收方接受一个数据包时,会发送一个ACK包。
确认包中的window size,代表了目前接收方的receiver buffer还能容纳多少数据,当window size=0,发送方停止发送数据。
receiver window指的是当前接收方能够连续不断接收数据量的最大值,也就是receiver buffer空闲区的大小。接收方应用程序不断地从receiver buffer里取走数据,receiver buffer也不断地从TCP发送方接收数据,所以receiver window的大小是不断动态变化的。当receiver window == 0,则表示receiver buffer已满,此时如果仍有数据包到来会直接抛弃。
receiver window(rwnd)的计算公式如下:
rwnd = ReceiveBuffer - (LastByteReceived – LastByteReadByApplication)
大家也可以看到了,这就是我们熟悉的滑动窗口。
窗口探测
什么是窗口探测
假设window size= 0,发送方已经停止发送,接收端最后一个包的ack也已经发送。此时发送端、接收端暂时没有数据交互。
但是接收方的应用端,一直在读取数据,receiverBuffer已经空闲,window size自然也是大于0了,双方如何继续后续的数据发送?
窗口探测,即WindowProbe,指的是,当TCP发送方收到window size == 0的通知而停止发送数据后,会启动一个持久化的定时器,定期发送一个数据量很小的数据包(因为主要作用是侦测,没有实际需要传输的业务数据),侦测window size的大小。当某个侦测包的确认包中window size != 0时,TCP发送方恢复发送实际数据。
拥塞控制
TCP发送方发送的数据包并不是一步直达接收方,而是跋山涉水,途经多个网络节点,最终抵达接收方。发送方发送的数据量虽然通过receiver window可以保证不超出接收方的处理能力,但必竟发送端和接收端,中间有这么多设备,在传输时,网络环境对于TCP是一个黑盒,如果超出网络承载的能力,毕依然会造成数据包丢失。
TCP拥堵控制机制就是避免TCP发送方抛出的数据量超出网络承载的能力,以及当出现网络拥堵后进行调整以消除拥堵。
说到拥塞控制,大家先了解几个概念
cogestion window:表明当前网络能够不受限制地连续接收的数据量大小
sender window:表示TCP发送方能够不受限制地连续向网络发送的数据量大小。
receiver window:接收方的处理数据量大小
sender window = cogestion window 和receiver window的最小值
主要有以下三个特性,来实现拥塞控制
慢启动
一个segment携带的最大数据量成为MSS(maximum segment size),在慢启动阶段,cogestion window设置为1MSS。
发送方每节收到一个ack,congestion window的大小加倍,依次为1MSS,2MSS,4MSS,8MSS...
通过这种方式,迅速增大。
拥塞规避
但是不能无限制的指数增长,有一个阈值:slow start threshold,大小为65535 个字节,当涨到这个大小,就不能指数级增加了,要慢下来。
这时候的增长为,收到一个ack,congestion window大小增加1/congestion window。比如congestion window=8,一次收到8个ack,那么
congestion window = 8 + 1/congestion window
这时候,变为线性增长。
拥堵探测
当然,线性增长,也会到一定的临界值,那什么时候判断是到了最终的临界值呢?
文章开头我们提到了,发送端发送数据包后会有一个定时器,用来判断是否需要重传。
当定时器出发,TCP认定存在拥塞, 此时,将sshresh设置为congestion window/2,congestion window 设置为1。重新开始慢启动。
大家可以发现,congestion window直接设置为1,直接回到解放前了,太极端了,明显会造成网络卡顿。因此这个算法已经废弃不用。
TCP当然没有这么笨,还记得我们提到的快重传吗?当发送方连续接到三个重复的ack,会执行“减法”算法,congestion window 减半为 congestion window/2,然后 sshthresh = congestion window。通过这样的方式,可以保证整体速度还是在一个比较高的水平。
仔细看下下图,更容易理解。
加餐-BBR
以上介绍的这些机制完美适应了1980年代的网络特征,低带宽,浅缓存队列,美好持续到了2000年代,互联网高速发展的时代开启了。
现在,几张图片几MB,一个短视频几十上百MB,宽带早已经猛增了,中间的网络设备缓存越来越大,传统的拥塞控制算法,似乎满足不了如今的网络环境了。
回到标题的那个问题,传统的TCP拥塞控制算法,在当今的网络环境下,有什么问题?
- 丢包并不代表着通道满了,可能信号干扰,设备损坏,这时候你就判定拥塞,降我网速,肯定不行
- 中间多层网络设备都满了,才会真正丢包,我非得塞满这些缓存,才降速吗,是不是反应太迟钝了?
BBR(Bottleneck Bandwidth and Round-trip time)拥塞控制算法是由Google开发的一种现代化的TCP拥塞控制算法。与传统的TCP拥塞控制算法(如TCP Cubic)相比,BBR采用了不同的工作原理和算法策略。
BBR拥塞控制算法具有以下几个显著的优势:
- 高带宽利用率:BBR算法通过准确估算网络的瓶颈带宽,能够充分利用可用的带宽资源。相比传统的拥塞控制算法,如TCP Cubic,它能够更有效地利用网络带宽,提供更高的吞吐量。
- 低延迟:BBR算法通过实时测量往返时间(RTT)和带宽来调整发送速率,以最小化网络延迟。它能够更快地适应网络变化,并通过动态的发送速率控制来减少排队延迟,从而提供更低的端到端延迟。
- 公平性:BBR算法采用了公平共享带宽的策略,以避免某些连接占据过多的带宽,导致其他连接的性能下降。它能够在网络负载较高的情况下,相对公平地分配带宽资源,确保多个连接能够公正地竞争带宽。
- 适应性:BBR算法具有较好的自适应性,能够根据网络条件的变化进行实时调整。它能够快速响应网络的带宽和延迟变化,自动调整发送速率,以适应不同的网络环境和拥塞程度。
- 丢包率减少:由于BBR算法采用了基于带宽和延迟的拥塞控制策略,它能够减少网络中的拥塞和丢包情况。相比传统算法,BBR能够更好地探测和应对网络拥塞,从而减少丢包率。
简单说几点,比如传统的拥塞控制,发生丢包时,就认为发生拥塞了。BBR并不care这些,更关注的是RTT。它通过观察发送数据包的出队情况和接收确认ACK的延迟时间,估计网络的瓶颈带宽,并使用这些信息来动态调整发送速率。BBR算法在设计上能够更好地识别和应对拥塞丢包,从而提供更好的网络性能和拥塞控制。
BBR算法还挺复杂的,在这里抛砖引玉吧,如果你有兴趣,可以自行去了解,这里就不展开啦。
说在最后
看到这里,相信你已经对TCP为什么这么”靠谱“有了一个简单的认识,当然,如果你第一次了解这部分内容,相信你已经被这些名词给看的眼花缭乱了,先复习一下基础概念
segment:数据包,TCP传输的最小单位
MSS(maximum segment size):一个segment携带最大的数据量
ack:接收方收到数据,告诉发送端数据确认
receiver window(rwnd):接收方的处理数据量大小
congestion window(cwnd):前网络能够不受限制地连续接收的数据量大小
ssthresh:慢开始门限,防止cwnd快速膨胀的一个阈值
RTT:一个数据包的往返时间
我们重点介绍了TCP的顺序问题,还有TCP很重要的流量控制和拥塞控制,顺便提了一嘴BBR算法。如果你还是有些模糊,建议你点赞收藏加关注,有事没事,看两眼。
不知道你是不是对TCP有了充分的了解呢,有没有什么想和大家分享的,欢迎你在评论区与我交流。看到这里,希望点赞评论支持一下,也欢迎你加我的wx:Ldhrlhy10 ,一起交流~