网络协议基础(三):TCP拥塞控制算法

TCP的几个重要的特性可以简单的表述为不丢包、不乱序、流量控制、拥塞控制。前三者其实在上一篇文章《TCP报文头部详解》讲解头部20字节加选项时已经具体介绍过了,并且扩展讲述了如何避免发送过多的小包问题,本节着重于研究我靠记忆而没有深入去理解的几个拥塞控制算法。

1.了解拥塞控制历史

  • 以丢包为依据
    应用于Linux2.6.19的CUBIC(RFC8312)算法是目前基于丢包为依据进行拥塞控制的主要方式
  • 以探测带宽作为依据
    最知名的就是BBR(应用于Linux4.9)算法

2.慢启动

  • 了解拥塞窗口cwnd(congestion window)
  • 通告窗口rwnd(receiver‘s advertised window)
    实际发送窗口swnd = min(cwnd,rwnd)

通过正常的网课学习,其实都明白在慢启动阶段拥塞窗口呈现指数型增长,那么试问慢启动初始窗口 IW(Initial Window)是怎样设计的哩?简单来说从设计的初始阶段为1*MSS,经过3*MSS,现在大多采用10*MSS.

3.拥塞避免

先认识一个背诵拥塞控制相关知识点时经常见到的名词ssthresh(slow start threshold),即慢启动阈值,当慢启动的拥塞窗口达到ssthresh时就会进入拥塞避免阶段,接下来就以一个具体的例子,看一看慢启动与拥塞避免的转化以及ssthresh的变迁。

在这里插入图片描述如上图所示在慢启动初始阶段,cwnd以指数性增长的方式增长,当达到ssthresh时进入拥塞避免阶段,其cwnd的增长规律见图中公式,之后当发生丢包时调整ssthresh为cwnd/2,并且重新设置cwnd开始慢重传的,慢恢复的过程。

4.快速重传与快速恢复

首先了解失序数据段,因为TCP会默认在内核缓冲区按序响应ACK报文,若报文丢失,将会产生连续的失序 ACK 段。除此之外, 若网络路径与设备导致数据段失序或者报文重复,也将会产生少量的失序 ACK 段。把这几种情况下的报文叫做失序数据段,而拥塞控制其实就是为了解决包丢失的问题,慢重传解决超时报文,快重传解决失序数据段的问题。

既然由上面以及了解了快重传的应用场景与具体举措,如下图所示展示了快速重传与快速恢复的具体过程:
快重传
恰如上图所示,在收到连续三个失序数据段的Ack之后发送方并不会等到RTO(超时定时器定时)到达,而是会立刻发送丢失的数据报。接收端在接收到填充失序缺口的数据段时,立刻发送它所期待的下一个 ACK 序列号,如上图所示收到丢失的包5之后,由于包7、8以及到达了,所以直接回Ack9即可 。在RFC2581文档中定义的快重传方式是将 ssthresh 设置为当前拥塞窗口 cwnd 的一半,设当前 cwnd 为 ssthresh 加上 3*MSS 。
然而存在的一个问题是,应该如何发送丢失的报文?因为发送方并不能确认丢失报文之后已发送的报文(如图中7,8)接收端是否已经收到,所以需要发送方选择一合适的方法来确认是只发送丢失的报文还是以后的报文也重新发送?

5.SACK与选择性重传算法

在第4节末尾,提出了一个疑问,我们常采用的方法有两种。

  • 保守乐观,即仅重传丢失段:在大量丢包时效率低下
  • 积极悲观,即重传所有段:可能浪费带宽

现在的问题是我们有没有一种更好的方法,使得两者兼顾哩?我们不仅想到了系统为减少IP层分包压力设计的MSS与计算RTT使用的字段Tcpstamps字段,它们都处于TCP报文头部的选项字段处,所以答案出来了,对于这种情况提出了选择性确认算法SACK(TCP Selective Acknowledgment
)。且当需要快重传时Ack报文的TCP报文头部的选项字段处有SACK字段,其指明了目前已接收到的后面报文序列号,这样重传时发送方就知道是应该采取乐观还是悲观的方式了。
下面是一个丢包报文,来瞅一瞅SACK,其隐含指出了已收到报文的相对序列号:
SAck

6.基于测量带宽的拥塞控制算法—BBR

常说的拥塞控制应该不仅解决丢包问题还应该解决网络资源紧缺的问题。前面讲的各个拥塞控制算法,无论是快重传还是慢重传都是针对丢包来设计的一系列应对措施,然而还是没有和带宽联系起来过,这次就来见识一下谷歌的BBR算法,其应用于QUIC协议。

  • 基于丢包的拥塞控制缺点
    高时延,大量丢包; 随着内存便宜,时延更高(主要是因为缓冲区变的更大了)
  • 最佳控制点
    最大带宽下;最小时延;最低丢包率

所以,如何准确测量带宽,提高效率?使用BBR拥塞控制算法(已加入Linux 4.9)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章