一个连接的TCP双端只是网络最边缘的两台主机,他们不知道整个网络是如何工作的,因此他们不知道彼此之间的有效吞吐量。因此,他们必须找到一种方法来确定它。我们称之为拥塞窗口 (CWND)。这是在我们必须停止并等待确认之前可以发送的字节数。
❝
拥塞窗口是决定任何时候可以发出的字节数的因素之一。拥塞窗口由发送方维护,是阻止发送方和接收方之间的链路因流量过多而过载的一种手段。这不应与发送方维护的滑动窗口相混淆,滑动窗口的存在是为了防止接收方过载。拥塞窗口是通过估计链路上有多少拥塞来计算的。
❞
拥塞窗口对于设备来说是本地的,并且永远不会在连接上共享,这与在每个段中发送的接收器窗口不同。在任何给定时间,设备最多可以发送由接收器窗口和拥塞窗口之间的最小值指定的字节数,如下面的公式所示:
transmittable bytes = min(cwnd, rwnd)
这意味着如果拥塞窗口小于接收窗口,则设备可以在等待确认之前传输多达拥塞窗口中定义的字节数。相反,如果接收窗口小于拥塞窗口,则设备可以在等待确认之前最多传输接收器窗口中定义的字节数。
拥塞窗口根据网络拥塞动态变化。每次未确认段时,都假定是由于网络拥塞。拥塞窗口随时间演变的方式被定义为一个算法,这取决于实现。我们现在将介绍最常见的一种。该算法遵循以下规则:
-
拥塞窗口从一个段的大小开始(大约 1KB)
-
定义了一个拥塞窗口阈值(ssthresh)
-
如果收到确认,并且当前拥塞窗口大小小于 ssthresh,则拥塞窗口加倍
-
如果收到确认,但拥塞窗口大于或等于 sshthresh,则拥塞窗口增加其初始值(例如 1KB)
-
如果一个段没有被确认从而触发重传,拥塞窗口就会减半并且 ssthresh 被放置在这个值
-
拥塞窗口不能大于接收器窗口
该规则中包括我们经常听过的几种算法:
-
慢启动(slow-start)
-
拥塞避免(congestion avoidance)
-
快速重传(fast retransmit)
-
快速恢复(fast recovery)
算法
–
通过下面的图片,可以方便大家更加快速的理解拥塞窗口的算法机制。
从上图中可以看出,每个设备都会跟踪自己的拥塞窗口(CWND,绿色)和对端的接收器窗口 (RWND)。
慢启动
当主机开始发送数据时,如果立即所大量数据字节注入到网络,那么就有可能引起网络拥塞,因为现在并不清楚网络的负荷情况。因此,较好的方法是先探测一下,即由小到大逐渐增大发送窗口,也就是说,由小到大逐渐增大拥塞窗口数值。通常在刚刚开始发送报文段时,先把拥塞窗口 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
-
重新进入拥塞避免阶段
快速恢复
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Java)
Kafka实战笔记
关于这份笔记,为了不影响大家的阅读体验,我只能在文章中展示部分的章节内容和核心截图
- Kafka入门
- 为什么选择Kafka
- Karka的安装、管理和配置
- Kafka的集群
- 第一个Kafka程序
afka的生产者
- Kafka的消费者
- 深入理解Kafka
- 可靠的数据传递
- Spring和Kalka的整合
- Sprinboot和Kafka的整合
- Kafka实战之削峰填谷
- 数据管道和流式处理(了解即可)
- Kafka实战之削峰填谷
一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
解即可)**
[外链图片转存中…(img-gGh8Xhbj-1712813849549)]
- Kafka实战之削峰填谷
[外链图片转存中…(img-cXg9CYxN-1712813849549)]
一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
[外链图片转存中…(img-A3JvElVh-1712813849549)]