当前位置: 首页 > news >正文

tcp拥塞控制原理

18.3 拥塞控制

我们在向对端发送数据时,并不是一股脑子任意发送,因为TCP建立连接后,就是建立了一根管道,这跟管道上,实际上有很多的工作设备,比如路由器和交换机等等,他们都会对接收到的TCP包进行缓存,以便实现排序,然后发送,但是这些设备并不是只为一个TCP连接中转数据包,大量的网络包也许会耗尽存储空间,从而导致TCP连接的吞吐量急剧下降。为了避免这种情况的发送,TCP的设计必须是一种无私的协议,它必须去探测这种网络拥塞的问题,否则我们想想,一旦出现拥塞(判断是否丢包或者是否发生重传),如果TCP只能做重传,那么重传数据包会使得网络上的包更多,网络的负担更重,于是导致更大的延迟以及丢更多的包,于是会进入一个恶性循环,如果网络上的所有TCP连接都是如此行事的话,那么马上就会形成“网络风暴”,会拖垮整个网络,这也是一个灾难。那么TCP就应该能够检测出来这种状况,当拥塞出现时,要做自我牺牲,就像交通阻塞一样,每一辆车都应该把路给让出来,而不是再去抢路了。这说的就是拥塞控制。那是如何控制的呢?

首先,我们得看TCP是如何充分利用网络的,TCP实际上就是逐步探测这个通道的传输的最大能力,这个逐步探索就是我们要讲的慢启动算法,这个慢启动算法就是:新建立的连接不能一开始就大量发送数据包,而是应该根据网络状况,逐步地增加每次发送数据包的量。

具体的工作步骤就是:

慢启动算法:

  1. 发送方维护一个拥塞窗口,刚开始时,这个拥塞窗口(cwnd,congestion window)设置为1,这个1代表是一个MSS个字节。

  2. 如果每收到一个ACK,那么就指数增长这个cwnd(2,4,8,16,32,64)等,

  3. 实际上不会这么一直指数级增长下去,TCP会设置一个慢启动的阈值(ssthresh,slow start threshold,65535个字节) ,当cwnd >= ssthresh时,进入拥塞避免阶段。

拥塞避免阶段

  1. 每收到一个ACK时,cwnd = cwnd + 1/cwnd;

  2. 每当每过一个RTT时,cwnd = cwnd + 1;

这样放缓了拥塞窗口的增长速率,避免增长过快导致网络拥塞,慢慢的增加调整到网络的最佳值。在这个过程中如果出现了拥塞,则进入拥塞状态。

拥塞状态
那是如何判断出现拥塞状态呢?只要出现丢包就认为进入了拥塞状态。进入拥塞状态也分两种情况:
1) 等到RTO超时(重传超时),重传数据包。TCP认为这种情况太糟糕,反应也很强烈:

  • sshthresh = cwnd /2
  • cwnd 重置为 1
  • 进入慢启动过程

快速重传
2)连续收到3个duplicate ACK时,重传数据包,无须等待RTO。此情况即为下面的快速重传。

【问题】什么情况下会出现3个duplicate ACK?

TCP在收到一个乱序的报文段时,会立即发送一个重复的ACK,并且此ACK不可被延迟。

如果连续收到3个或3个以上重复的ACK,TCP会判定此报文段丢失,需要重新传递,而无需等待RTO。这就叫做快速重传。

TCP Tahoe的实现和RTO超时一样。
TCP Reno的实现是:

  • sshthresh = cwnd
  • cwnd = cwnd /2
  • 进入快速恢复算法——Fast Recovery

上面我们可以看到RTO超时后,sshthresh会变成cwnd的一半,这意味着,如果cwnd<=sshthresh时出现的丢包,那么TCP的sshthresh就会减了一半,然后等cwnd又很快地以指数级增涨爬到这个地方时,就会成慢慢的线性增涨。我们可以看到,TCP是怎么通过这种强烈地震荡快速而小心得找到网站流量的平衡点的。

快速恢复算法

TCP Reno

这个算法定义在RFC5681。快速重传和快速恢复算法一般同时使用。快速恢复算法是认为,你还有3个Duplicated Acks说明网络也不那么糟糕,所以没有必要像RTO超时那么强烈。 注意,正如前面所说,进入Fast Recovery之前,cwnd 和 sshthresh已被更新:

  • sshthresh = cwnd
  • cwnd = cwnd /2

然后,真正的Fast Recovery算法如下:

  • cwnd = sshthresh + 3 * MSS (3的意思是确认有3个数据包被收到了)
  • 重传Duplicated ACKs指定的数据包
  • 如果再收到 duplicated Acks,那么cwnd = cwnd +1
  • 如果收到了新的Ack,那么,cwnd = sshthresh ,代表恢复过程结束,然后就进入了拥塞避免的算法了。

如果我们仔细思考一下上面的这个算法,你就会知道,上面这个算法也有问题,那就是——它依赖于3个重复的Acks。注意,3个重复的Acks并不代表只丢了一个数据包,很有可能是丢了好多包。但这个算法只会重传一个,而剩下的那些包只能等到RTO超时,于是,进入了恶梦模式——超时一个窗口就减半一下,多个超时会超成TCP的传输速度呈级数下降,而且也不会触发Fast Recovery算法了。

TCP New Reno

于是,1995年,TCP New Reno(参见 RFC 6582 )算法提出来:

  • 当sender这边收到了3个Duplicated Acks,进入Fast Retransimit模式,开发重传重复Acks指示的那个包。如果只有这一个包丢了,那么,重传这个包后回来的Ack会把整个已经被sender传输出去的数据ack回来。如果没有的话,说明有多个包丢了。我们叫这个ACK为Partial ACK。
  • 一旦Sender这边发现了Partial ACK出现,那么,sender就可以推理出来有多个包被丢了,于是乎继续重传sliding window里未被ack的第一个包。直到再也收不到了Partial Ack,才真正结束Fast Recovery这个过程。

我们可以看到,这个“Fast Recovery的变更”是一个非常激进的玩法,他同时延长了Fast Retransmit和Fast Recovery的过程。

18.4 BBR算法

上一小节,我们接收了两种拥塞控制算法,一个是Reno、一个是New Reno,现如今,google研发了新的拥塞控制算法BBR,详情见:https://www.zhihu.com/question/53559433

对于BBR算法的测试结果可以参考:
https://www.zhihu.com/question/52933117

那我们如何修改拥塞控制算法呢?

  • 首先我们要确保我们是否升级到了4.9版本,使用uname -r 或者uname -a
lizhiyong@ubuntu:~$ uname -r
4.4.0-87-generic
lizhiyong@ubuntu:~$ uname -a
Linux ubuntu 4.4.0-87-generic #110-Ubuntu SMP Tue Jul 18 12:55:35 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
lizhiyong@ubuntu:~$
  • 下载linux内核代码方法:到官网下载https://www.kernel.org/
    或者git:https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/

升级内核版本的方法:https://kernelnewbies.org/KernelBuild

修改内核使用的拥塞控制算法:

更新完系统内核之后,就可以开启TCP-BBR了。

  1. 编辑/etc/sysctl.conf,并保存

#在文件最底部添加如下两行,如果之前已经有这些内容,请酌情删掉或修改
net.core.default_qdisc=fq
net.ipv4.tcp_congestion_control=bbr

  1. 执行sysctl -p使修改后的配置文件生效
    root@linode:~# sysctl -p
    net.core.default_qdisc = fq
    net.ipv4.tcp_congestion_control = bbr

  2. 查看BBR是否开启

首先,执行下边的命令来确定内核已经开启BBR(如果返回的结果中含有BBR则证明内核已经开启):

sysctl net.ipv4.tcp_available_congestion_control
然后,执行下边的命令,看到有tcp_bbr模块,则说明BBR已经启动:

lsmod | grep bbr

相关文章:

tcp拥塞控制原理

18.3 拥塞控制 我们在向对端发送数据时&#xff0c;并不是一股脑子任意发送&#xff0c;因为TCP建立连接后&#xff0c;就是建立了一根管道&#xff0c;这跟管道上&#xff0c;实际上有很多的工作设备&#xff0c;比如路由器和交换机等等&#xff0c;他们都会对接收到的TCP包进…...

【C++设计模式之简单工厂模式】分析及示例

简介 简单工厂模式是一种常见的设计模式&#xff0c;用于创建多种相似对象的实例&#xff0c;属于创建型。 它通过一个工厂类来解耦客户端代码和对象的创建过程&#xff0c;使得客户端无需直接和具体的产品类交互&#xff0c;而只需要通过工厂类获取所需的产品实例即可。 原理…...

云原生定义整理

云原生定义整理 Pivotal 是云原生应用的提出者&#xff0c;并推出了 Pivotal Cloud Foundry 云原生应用平台和 Spring 开源 Java 开发框架&#xff0c;成为云原生应用架构中先驱者和探路者。 Pivotal最初的定义 Pivotal公司的Matt Stine在2015年写了一本叫做<<迁移到云…...

华硕X555YI, Win11下无法调节屏幕亮度

翻出一个旧电脑华硕X555YI&#xff0c;装Win11玩&#xff0c;已经估计到会有一些问题。 果然&#xff0c;装完之后&#xff0c;发现屏幕无法调节亮度。试了网上的一些方法&#xff0c;比如修改注册表等&#xff0c;无效。 估计是显卡比较老&#xff0c;哪里没兼容。然后用驱动…...

踩坑 | vue动态绑定img标签src属性的一系列报错

文章目录 踩坑 | vue项目运行后使用require()图片也不显示问题描述vue中动态设置img的src不生效问题的原因require is not defined 解决办法1&#xff1a;src属性直接传入地址解决办法2 踩坑 | vue项目运行后使用require()图片也不显示 问题描述 在网上查阅之后&#xff0c;发…...

强化学习环境 - robogym - 学习 - 1

强化学习环境 - robogym - 学习 - 1 项目地址 https://github.com/openai/robogym 为什么选择 robogym 自己的项目需要做一些机械臂 table-top 级的多任务操作 robogym 基于 mujoco 搭建&#xff0c;构建了一个仿真机械臂桌面物体操作&#xff08;pick-place、stack、rearr…...

如果在 Mac 上的 Safari 浏览器中无法打开网站

使用网络管理员提供的信息更改代理设置。个人建议DNS解析&#xff0c;设置多个例如114.114.114.114 8.8.8.8 8.8.4.4 如果打不开网站&#xff0c;请尝试这些建议。 在 Mac 上的 Safari 浏览器 App 中&#xff0c;检查页面无法打开时出现的信息。 这可能会建议解决问题的…...

力扣练习——链表在线OJ

目录 提示&#xff1a; 一、移除链表元素 题目&#xff1a; 解答&#xff1a; 二、反转链表 题目&#xff1a; 解答&#xff1a; 三、找到链表的中间结点 题目&#xff1a; 解答&#xff1a; 四、合并两个有序链表&#xff08;经典&#xff09; 题目&#xff1a; 解…...

四、互联网技术——局域网拓扑结构

文章目录 一、局域网拓扑结构二、虚拟局域网VLAN三、交换机VLAN划分四、VLAN的作用五、交换机的端口类型六、经典三层网络架构七、例题:局域网带宽利用分析八、网络安全基础九、恶意软件十、防火墙与入侵检测技术 一、局域网拓扑结构 局域网的主要特征由网络的拓扑结构、所采用…...

Spring Webflux DispatcherHandler源码整理

DispatcherHandler的构造(以RequestMappingHandlerMapping为例) WebFluxAutoConfiguration中EnableWebFluxConfiguration继承WebFluxConfigurationSupportBean public DispatcherHandler webHandler() {return new DispatcherHandler(); }DispatcherHandler#setApplicationCon…...

【Netty】ByteToMessageDecoder源码解析

目录 1.协议说明 2.类的实现 3.Decoder工作流程 4.源码解析 4.1 ByteToMessageDecoder#channelRead 4.2 累加器Cumulator 4.3 解码过程 4.4 Decoder实现举例 5. 如何开发自己的Decoder 1.协议说明 Netty框架是基于Java NIO框架&#xff0c;性能彪悍&#xff0c;支持的协…...

DevEco Studio设置Nodejs提示路径只能包含英文、数字、下划线等

安装DevEco Studio 3.1.1 Release 设置Nodejs路径使用nodejs默认安装路径 &#xff08;C:\Program Files\nodejs&#xff09; 提示只能包含英文、数字、下划线等 , 不想在安装nodejs请往下看 nodejs默认路径报错 修改配置文件 1、退出DevEco Studio 2、打开配置文件 cmd控制台…...

大模型 Decoder 的生成策略

本文将介绍以下内容&#xff1a; IntroductionGreedy Searchbeam searchSamplingTop-K SamplingTop-p (nucleus) sampling总结 一、Introduction 1、简介 近年来&#xff0c;由于在数百万个网页数据上训练的大型基于 Transformer 的语言模型的兴起&#xff0c;开放式语言生…...

队列和栈相互实现

相关题目 225. 用队列实现栈&#xff1a;弹出元素时&#xff0c;将对首的元素出列加到队尾&#xff0c;直到只剩下初始队列时队尾一个元素为止&#xff0c;然后弹出这个元素&#xff0c;即可实现LIFO 232. 用栈实现队列&#xff1a;用两个栈实现队列的功能&#xff0c;出栈时&a…...

Node.js 是如何处理请求的

前言&#xff1a;在服务器软件中&#xff0c;如何处理请求是非常核心的问题。不管是底层架构的设计、IO 模型的选择&#xff0c;还是上层的处理都会影响一个服务器的性能&#xff0c;本文介绍 Node.js 在这方面的内容。 TCP 协议的核心概念 要了解服务器的工作原理首先需要了…...

数据结构与算法之堆: Leetcode 215. 数组中的第K个最大元素 (Typescript版)

数组中的第K个最大元素 https://leetcode.cn/problems/kth-largest-element-in-an-array/ 描述 给定整数数组 nums 和整数 k&#xff0c;请返回数组中第 k 个最大的元素。请注意&#xff0c;你需要找的是数组排序后的第 k 个最大的元素&#xff0c;而不是第 k 个不同的元素。…...

SpringBoot快速入门

搭建SpringBoot工程&#xff0c;定义hello方法&#xff0c;返回“Hello SpringBoot” ②导入springboot工程需要继承的父工程&#xff1b;以及web开发的起步依赖。 ③编写Controller ④引导类就是SpringBoot项目的一个入口。 写注解写main方法调用run方法 快速构建SpringBoo…...

深度学习笔记_4、CNN卷积神经网络+全连接神经网络解决MNIST数据

1、首先&#xff0c;导入所需的库和模块&#xff0c;包括NumPy、PyTorch、MNIST数据集、数据处理工具、模型层、优化器、损失函数、混淆矩阵、绘图工具以及数据处理工具。 import numpy as np import torch from torchvision.datasets import mnist import torchvision.transf…...

高效的开发流程搭建

目录 1. 搭建 AI codebase 环境kaggle的服务器1. 搭建 AI codebase 环境 python 、torch 以及 cuda版本,对AI的影响最大。不同的版本,可能最终计算出的结果会有区别。 硬盘:PCIE转SSD的卡槽,, GPU: 软件源: Anaconda: 一定要放到固态硬盘上。 VS code 的 debug功能…...

浅谈OV SSL 证书的优势

随着网络威胁日益增多&#xff0c;保护网站和用户安全已成为每个企业和组织的重要任务。在众多SSL证书类型中&#xff0c;OV&#xff08;Organization Validation&#xff09;证书以其独特的优势备受关注。让我们深入探究OV证书的优势所在&#xff0c;为网站安全搭建坚实的防线…...

(十)学生端搭建

本次旨在将之前的已完成的部分功能进行拼装到学生端&#xff0c;同时完善学生端的构建。本次工作主要包括&#xff1a; 1.学生端整体界面布局 2.模拟考场与部分个人画像流程的串联 3.整体学生端逻辑 一、学生端 在主界面可以选择自己的用户角色 选择学生则进入学生登录界面…...

java调用dll出现unsatisfiedLinkError以及JNA和JNI的区别

UnsatisfiedLinkError 在对接硬件设备中&#xff0c;我们会遇到使用 java 调用 dll文件 的情况&#xff0c;此时大概率出现UnsatisfiedLinkError链接错误&#xff0c;原因可能有如下几种 类名错误包名错误方法名参数错误使用 JNI 协议调用&#xff0c;结果 dll 未实现 JNI 协…...

Go 语言接口详解

Go 语言接口详解 核心概念 接口定义 在 Go 语言中&#xff0c;接口是一种抽象类型&#xff0c;它定义了一组方法的集合&#xff1a; // 定义接口 type Shape interface {Area() float64Perimeter() float64 } 接口实现 Go 接口的实现是隐式的&#xff1a; // 矩形结构体…...

【大模型RAG】Docker 一键部署 Milvus 完整攻略

本文概要 Milvus 2.5 Stand-alone 版可通过 Docker 在几分钟内完成安装&#xff1b;只需暴露 19530&#xff08;gRPC&#xff09;与 9091&#xff08;HTTP/WebUI&#xff09;两个端口&#xff0c;即可让本地电脑通过 PyMilvus 或浏览器访问远程 Linux 服务器上的 Milvus。下面…...

用docker来安装部署freeswitch记录

今天刚才测试一个callcenter的项目&#xff0c;所以尝试安装freeswitch 1、使用轩辕镜像 - 中国开发者首选的专业 Docker 镜像加速服务平台 编辑下面/etc/docker/daemon.json文件为 {"registry-mirrors": ["https://docker.xuanyuan.me"] }同时可以进入轩…...

学校时钟系统,标准考场时钟系统,AI亮相2025高考,赛思时钟系统为教育公平筑起“精准防线”

2025年#高考 将在近日拉开帷幕&#xff0c;#AI 监考一度冲上热搜。当AI深度融入高考&#xff0c;#时间同步 不再是辅助功能&#xff0c;而是决定AI监考系统成败的“生命线”。 AI亮相2025高考&#xff0c;40种异常行为0.5秒精准识别 2025年高考即将拉开帷幕&#xff0c;江西、…...

Java线上CPU飙高问题排查全指南

一、引言 在Java应用的线上运行环境中&#xff0c;CPU飙高是一个常见且棘手的性能问题。当系统出现CPU飙高时&#xff0c;通常会导致应用响应缓慢&#xff0c;甚至服务不可用&#xff0c;严重影响用户体验和业务运行。因此&#xff0c;掌握一套科学有效的CPU飙高问题排查方法&…...

AI病理诊断七剑下天山,医疗未来触手可及

一、病理诊断困局&#xff1a;刀尖上的医学艺术 1.1 金标准背后的隐痛 病理诊断被誉为"诊断的诊断"&#xff0c;医生需通过显微镜观察组织切片&#xff0c;在细胞迷宫中捕捉癌变信号。某省病理质控报告显示&#xff0c;基层医院误诊率达12%-15%&#xff0c;专家会诊…...

推荐 github 项目:GeminiImageApp(图片生成方向,可以做一定的素材)

推荐 github 项目:GeminiImageApp(图片生成方向&#xff0c;可以做一定的素材) 这个项目能干嘛? 使用 gemini 2.0 的 api 和 google 其他的 api 来做衍生处理 简化和优化了文生图和图生图的行为(我的最主要) 并且有一些目标检测和切割(我用不到) 视频和 imagefx 因为没 a…...

深入理解Optional:处理空指针异常

1. 使用Optional处理可能为空的集合 在Java开发中&#xff0c;集合判空是一个常见但容易出错的场景。传统方式虽然可行&#xff0c;但存在一些潜在问题&#xff1a; // 传统判空方式 if (!CollectionUtils.isEmpty(userInfoList)) {for (UserInfo userInfo : userInfoList) {…...