likes
comments
collection
share

面试官:我说传统TCP的拥塞控制算法有问题,说说什么情况下他会误判?

作者站长头像
站长
· 阅读数 8

前言

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包。

面试官:我说传统TCP的拥塞控制算法有问题,说说什么情况下他会误判?

确认包中的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的最小值

主要有以下三个特性,来实现拥塞控制

慢启动

面试官:我说传统TCP的拥塞控制算法有问题,说说什么情况下他会误判?

一个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。通过这样的方式,可以保证整体速度还是在一个比较高的水平。

仔细看下下图,更容易理解。

面试官:我说传统TCP的拥塞控制算法有问题,说说什么情况下他会误判?

加餐-BBR

以上介绍的这些机制完美适应了1980年代的网络特征,低带宽,浅缓存队列,美好持续到了2000年代,互联网高速发展的时代开启了。

现在,几张图片几MB,一个短视频几十上百MB,宽带早已经猛增了,中间的网络设备缓存越来越大,传统的拥塞控制算法,似乎满足不了如今的网络环境了。

回到标题的那个问题,传统的TCP拥塞控制算法,在当今的网络环境下,有什么问题?

  1. 丢包并不代表着通道满了,可能信号干扰,设备损坏,这时候你就判定拥塞,降我网速,肯定不行
  2. 中间多层网络设备都满了,才会真正丢包,我非得塞满这些缓存,才降速吗,是不是反应太迟钝了?

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 ,一起交流~