现在java后端的主流技术,TCP 拥塞窗口原理

本文详细介绍了TCP协议中的慢启动机制、拥塞避免算法,以及快速重传和快速恢复策略。重点阐述了如何通过调整拥塞窗口cwnd来适应网络状况,以优化数据传输效率和防止网络拥塞。
摘要由CSDN通过智能技术生成

慢启动

当主机开始发送数据时,如果立即所大量数据字节注入到网络,那么就有可能引起网络拥塞,因为现在并不清楚网络的负荷情况。因此,较好的方法是先探测一下,即由小到大逐渐增大发送窗口,也就是说,由小到大逐渐增大拥塞窗口数值。通常在刚刚开始发送报文段时,先把拥塞窗口 cwnd 设置为一个最大报文段MSS的数值。而在每收到一个对新的报文段的确认后,把拥塞窗口增加至多一个MSS的数值。用这样的方法逐步增大发送方的拥塞窗口 cwnd ,可以使分组注入到网络的速率更加合理。

每经过一个传输轮次,拥塞窗口 cwnd 就加倍。一个传输轮次所经历的时间其实就是往返时间RTT。不过“传输轮次”更加强调:把拥塞窗口cwnd所允许发送的报文段都连续发送出去,并收到了对已发送的最后一个字节的确认。

另,慢开始的“慢”并不是指cwnd的增长速率慢,而是指在TCP开始发送报文段时先设置cwnd=1,使得发送方在开始时只发送一个报文段(目的是试探一下网络的拥塞情况),然后再逐渐增大cwnd。

下面,我们从示例图着手,来分析慢启动的过程。

  • 在协商连接时,两个设备交换它们的接收器窗口(在这种情况下它们都有 32KB)

  • 双端都以 1KB 的拥塞窗口开始,但由于在该示例中客户端将是唯一发送数据的客户端,因此它将是唯一一个显着使用此值的客户端。

  • 在第 2 行,客户端收到一个 ACK并将其 CWND 加倍(现在是 2k)

  • 服务器在第 3 行收到一个ACK时也做同样的事情

  • 客户端发送两段 1k 的数据,它们稍后在第 6 行和第 7 行确认,其中客户端上的拥塞窗口加倍(4k,然后是 8k)

  • 然后,客户端再次发送 1k 数据并立即得到确认,有效地再次将拥塞窗口加倍(现在第 9 行为 16k)。

  • 这在第 10-11 行重复,其中 CWND 达到 32k。

  • 此时,除非接收端窗口也增长,否则拥塞窗口不能再增长。

慢启动的整个过程如下:

  • 初始化 cwnd = 1

  • 经过1个RTT,即收到一个ACK,cwnd = 2^(1) = 2

  • 经过2个RTT, cwnd = 2^(2) = 4

  • 经过3个 RTT, cwnd = 2^(3) = 8

拥塞避免

让拥塞窗口cwnd缓慢地增大,即每经过一个往返时间RTT就把发送方的拥塞窗口cwnd加1,而不是加倍。这样拥塞窗口cwnd按线性规律缓慢增长,比慢开始算法的拥塞窗口增长速率缓慢得多。

无论在慢启动阶段还是在拥塞避免阶段,只要发送方判断网络出现拥塞(其根据就是没有收到确认),就要把慢启动ssthresh设置为出现拥塞时的发送方窗口值的一半(但不能小于2)。然后把拥塞窗口cwnd重新设置为1,执行慢开始算法。这样做的目的就是要迅速减少主机发送到网络中的分组数,使得发生 拥塞的路由器有足够时间把队列中积压的分组处理完毕。

“拥塞避免”并非指完全能够避免了拥塞。利用以上的措施要完全避免网络拥塞还是不可能的。“拥塞避免”是说在拥塞避免阶段将拥塞窗口控制为按线性规律增长,使网络比较不容易出现拥塞

  • cwnd = i

  • 经过 1 RTT, cwnd = i+1

  • 2 RTT, cwnd = i+2

  • 3 RTT, cwnd = i+3

快速重传

TCP 有一个快速传输特性——在它的计时器到期之前重新传输丢失的段。 为了允许快速传输,我们需要为发送方和接收方设置一些规则。

  • 作为接收者,它应该始终发送它期望接收的序列号。 例如,当接收方接收到第 1 段时,它以 ACK2 响应,

  • 作为发送方,它应该忽略定时器并在收到 3 个重复的ACK 后立即开始重传丢失的段。

用一句话概况,就是发送端在收到3个重复无序的ACK时候,它假定数据包丢失并重传该数据包,而无需等待重传计时器到期。

而在此时,拥塞窗口的变化过程如下:

  • ssthresh设置为拥塞窗口的1/2

  • 拥塞窗口大小设置为ssthresh

  • 重新进入拥塞避免阶段

快速恢复

  • 当收到第3个重复的ACK时,将ssthresh设置为当前拥塞窗口cwnd的一半。重传丢失的报文段。设置cwnd为ssthresh加上3倍的报文段大小。

  • 每次收到另一个重复的ACK时,cwnd增加1个报文段大小并发送1个分组(如果新的cwnd允许发送)。

  • 当下一个确认新数据的ACK到达时,设置cwnd为ssthresh(在第1步中设置的值)。这个ACK应该是在进行重传后的一个往返时间内对步骤1中重传的确认。另外,这个ACK也应该是对丢失的分组和收到的第1个重复的ACK之间的所有中间报文段的确认。这一步采用的是拥塞避免,因为当分组丢失时我们将当前的速率减半。

算法

快速重传和快速恢复的目的是:快速恢复丢失的数据包。 如果没有快速重传和快速恢复这俩算法,那么tcp可能

Tahoe

Tahoe算法是TCP的早期版本。除了具备TCP的基本架构和功能外,引入了慢启动、拥塞避免以及快速重传机制。 在该算法中,快速重传机制策略如下:

  • ssthresh设置为拥塞窗口的1/2

  • 拥塞窗口大小设置为1

  • 重新进入慢启动阶段

Reno

Reno与Tahoe相比,增加了快速恢复阶段,也就是说,完成快速重传后,进入了拥塞避免阶段而不是慢 启动阶段。 Reno 在快速重传阶段,重新发送数据之后:

  • ssthresh设置为拥塞窗口的1/2

  • 拥塞窗口设置为之前的1/2

  • 进入快速恢复阶段

  • 在快速恢复阶段,每收到重复的ACK,则cwnd加1;收到非重复ACK时,置cwnd = ssthresh,转入拥塞避免阶段;

  • 如果发生超时重传,则置ssthresh为当前cwnd的一半,cwnd = 1,重新进入慢启动阶段。

Reno快速恢复阶段退出条件:收到非重复ACK。

NewReno

在Reno版本中,若同时有多个数据包丢失,则大部分必须等到TimeOut之后,才进行重传。这是因为在Reno中,同时有多个数据包丢失时,只要收到部分丢失数据的ACK,便退出快速恢复。而之所以能收到部分丢失数据的ACK,这是因为在快速重传阶段,只重新发送了部分丢失的数据。而在Reno结束快速恢复,进入拥塞避免阶段之后,对于其他未重新发送的数据包来说,常常没有足够的重复ACK来触发快速重传机制。只好等等TimeOut,而TimeOut对于TCP性能有非常大的影响,在等待TimeOut这段时间,无法发送新的数据包,而在TimeOut之后,CWND被重新设置为1。

基于上述原因,NewReno优化了该机制,NewReno在收到部分丢失数据的ACK后,并不会退出快速恢复阶段,而是等待所有丢失的包都重新发送之后,才退出快速恢复阶段。这就使得NewReno在遇到多个数据包同时丢失时,不需要等待TimeOut,便可重新发送所有丢失的数据包,进而减小TimeOut对性能的影响。

SACK

除了NewReno的方法之外,要解决大量数据包丢失的问题,还有一个解决方案,就是让发送端知道,哪些数据包已经送达,哪些数据包已经丢失。 SACK修改在接收端发送重复的ACK时,同时在ACK中携带连续的已经收到的数据序列号范围,而连续数据序号范围与连续数据序号范围之间的间隔就是已经丢失的数据。

滑动窗口与拥塞窗口


共同点:提高网络性能。

不同点:

  • 流量控制:在TCP连接上实现对发送流量的控制,考虑点对点之间对通信量的控制,端到端,即:控制发送端的数据发送速率,使接收端可以来得及接收,保证网络高效稳定运行。

  • 拥塞控制:处理网络拥塞现象,考虑网络能够承受现有的网络负荷,全局性变量,涉及所有的路由器、主机以及与降低网络传输性能有关的因素。防止过多的数据注入到网络,使网络中的路由器或链路不致过载,确保通信子网可以有效为主机传递分组。

Q&A


1、在一个窗口内重复丢包会造成影响吗? 会。如果只丢一个包,那么收到非重复ACK时,就能确认完本窗口内所有的包。然后进入拥塞 避免阶段。这就是Reno想达到的。 而如果丢失多个包,那么收到非重复ACK时,不能确认完本窗口内所有的包。但是,也会退出快速恢复, 进入拥塞避免阶段。

这个时候可能会发生两种情况:
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)

img

总结

我们总是喜欢瞻仰大厂的大神们,但实际上大神也不过凡人,与菜鸟程序员相比,也就多花了几分心思,如果你再不努力,差距也只会越来越大。实际上,作为程序员,丰富自己的知识储备,提升自己的知识深度和广度是很有必要的。

Mybatis源码解析

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
丰富自己的知识储备,提升自己的知识深度和广度是很有必要的。

Mybatis源码解析

[外链图片转存中…(img-lTe8kdCf-1713573627243)]

[外链图片转存中…(img-gja6lCoV-1713573627244)]

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

  • 10
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值