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

异步为什么会造成 HTTP 队首阻塞?

一、http 协议的队首阻塞

队首阻塞,队首的事情没有处理完的时候,后面的都要等着。

1.1 HTTP1.0 的队首阻塞

对于同一个 tcp 连接,所有的 http1.0 请求放入队列中,只有前一个请求的响应收到了,然后才能发送下一个请求。http1.0 的队首组塞发生在客户端。

1.2 HTTP1.1 的队首阻塞

HTTP1.1 版本上使用了一种 Pipelining 管道技术来并行发送和处理多个请求。让客户端能够并行发送多个请求,服务器端也可以并行处理多个来自客户端的请求。在一个 TCP 连接中,发送多个 HTTP 请求,不需要等待服务器端对前一个请求的响应之后,再发送下一个请求。但是使用了管道技术的 HTTP/1.1,根据 HTTP/1.1 的规则,服务器端在响应时,要严格按照接收请求的顺序发送,即先接收到的请求,需要先发送其响应,客户端浏览器也是如此,接收响应的顺序要按照自己发送请求的顺序来。这样造成的问题是,如果 最先收到的请求的处理时间长的话,响应生成也慢,就会阻塞已经生成了的响应的发送。也会造成队首阻塞。

总的来说,管道技术允许客户端和服务器端并行发送多个请求和响应,但是客户端接收响应的顺序要和自己发送请求的顺序对应,服务器端发送响应的顺序要和自己接收到的请求的顺序对应,这样做似乎没什么问题,看起来是不是“FIFO”先来先服务的方式,如果前面收到的一个请求,在服务器端处理的时间很长,生成响应需要很多时间,那么对于后面的已经处理完生成响应的请求来说,它们只能阻塞等待,等待前面的响应发送完后,自己才能被发送出去(即使该请求的响应已经生成),造成了“队首阻塞”问题。可见队首阻塞发生在服务器端,虽然服务器端并行接收了多个请求,也并行处理生成多个响应,但由于要遵守 HTTP/1.1 的规则,先接收到的请求需要先发送响应,造成了阻塞问题。

另外需要注意的是,虽然 HTTP/1.1 规范中规定了 Pipelining 管道技术来并行发送和处理多个请求,但是这个功能在浏览器中默认是关闭的。

看一下 Pipelining 是什么,RFC 2616 中的规定 A client that supports persistent connections MAY “pipeline” its requests (i.e., send multiple requests without waiting for each response). A server MUST send its responses to those requests in the same order that the requests were received. 一个支持持久连接的客户端可以在一个连接中发送多个请求(不需要等待任意请求的响应)。收到请求的服务器必须按照请求收到的顺序发送响应。 至于标准为什么这么设定,我们可以大概推测一个原因:由于 HTTP/1.1 是个文本协议,同时返回的内容也并不能区分对应于哪个发送的请求,所以顺序必须维持一致。比如你向服务器发送了两个请求 GET /query?q=A 和 GET /query?q=B,服务器返回了两个结果,浏览器是没有办法根据响应结果来判断响应对应于哪一个请求的。

Pipelining 这种设想看起来比较美好,但是在实践中会出现许多问题:

  • 一些代理服务器不能正确的处理 HTTP Pipelining。
  • 正确的流水线实现是复杂的
  • Head-of-line Blocking 连接头阻塞:在建立起一个 TCP 连接之后,假设客户端在这个连接连续向服务器发送了几个请求。按照标准,服务器应该按照收到请求的顺序返回结果,假设服务器在处理首个请求时花费了大量时间,那么后面所有的请求都需要等着首个请求结束才能响应。

所以现代浏览器默认是不开启 HTTP Pipelining 的。

1.3 HTTP2 队首阻塞

对于 HTTP1.1 中管道化导致的请求/响应级别的队头阻塞,可以使用 HTTP2 解决。HTTP2 不使用管道化的方式,而是引入了帧、消息和数据流等概念,每个请求/响应被称为消息,每个消息都被拆分成若干个帧进行传输,每个帧都分配一个序号。每个帧在传输是属于一个数据流,而一个连接上可以存在多个流,各个帧在流和连接上独立传输,到达之后在组装成消息,这样就避免了请求/响应阻塞。

当然,即使使用 HTTP2,如果 HTTP2 底层使用的是 TCP 协议,仍可能出现 TCP 队头阻塞。因为 HTTP/2 并没有解决 TCP 的队首阻塞问题,它仅仅是通过多路复用解决了以前 HTTP1.1 管线化请求时的队首阻塞。比如 HTTP/1.1 时代建立一个 TCP 连接,三个请求组成一个队列发出去,服务器接收到这个队列之后会依次响应,一旦前面的请求阻塞,后面的请求就会无法响应。HTTP/2 是通过分帧并且给每个帧打上流的 ID 去避免依次响应的问题,对方接收到帧之后根据 ID 拼接出流,这样就可以做到乱序响应从而避免请求时的队首阻塞问题。但是 TCP 层面的队首阻塞是 HTTP/2 无法解决的(HTTP 只是应用层协议,TCP 是传输层协议),TCP 的阻塞问题是因为传输阶段可能会丢包,一旦丢包就会等待重新发包,阻塞后续传输,这个问题虽然有滑动窗口(Sliding Window)这个方案,但是只能增强抗干扰,并没有彻底解决。

二、TCP 队首阻塞

队首阻塞(head-of-line blocking)发生在一个 TCP 分节丢失,导致其后续分节不按序到达接收端的时候。该后续分节将被接收端一直保持直到丢失的第一个分节被发送端重传并到达接收端为止。该后续分节的延迟递送确保接收应用进程能够按照发送端的发送顺序接收数据。这种为了达到完全有序而引入的延迟机制非常有用,但也有不利之处。

假设在单个 TCP 连接上发送语义独立的消息,比如说服务器可能发送 3 幅不同的图像供 Web 浏览器显示。为了营造这几幅图像在用户屏幕上并行显示的效果,服务器先发送第一幅图像的一个断片,再发送第二幅图像的一个断片,然后再发送第三幅图像的一个断片;服务器重复这个过程,直到这 3 幅图像全部成功地发送到浏览器为止。

要是第一幅图像的某个断片内容的 TCP 分节丢失了,客户端将保持已到达的不按序的所有数据,直到丢失的分节重传成功。这样不仅延缓了第一幅图像数据的递送,也延缓了第二幅和第三幅图像数据的递送。

2.1 如何解决 TCP 队头阻塞

TCP 中的队头阻塞的产生是由 TCP 自身的实现机制决定的,无法避免。想要在应用程序当中避免 TCP 队头阻塞带来的影响,只有舍弃 TCP 协议。

比如 google 推出的 quic 协议,在某种程度上可以说避免了 TCP 中的队头阻塞,因为它根本不使用 TCP 协议,而是在 UDP 协议的基础上实现了可靠传输。而 UDP 是面向数据报的协议,数据报之间不会有阻塞约束。

此外还有一个 SCTP(流控制传输协议),它是和 TCP、UDP 在同一层次的传输协议。SCTP 的多流特性也可以尽可能的避免队头阻塞的情况。

三、总结

从 TCP 队头阻塞和 HTTP 队头阻塞的原因我们可以看到,出现队头阻塞的原因有两个:

  • 独立的消息数据都在一个链路上传输,也就是有一个“队列”。比如 TCP 只有一个流,多个 HTTP 请求共用一个 TCP 连接
  • 队列上传输的数据有严格的顺序约束。比如 TCP 要求数据严格按照序号顺序,HTTP 管道化要求响应严格按照请求顺序返回

所以要避免队头阻塞,就需要从以上两个方面出发,比如 quic 协议不使用 TCP 协议而是使用 UDP 协议,SCTP 协议支持一个连接上存在多个数据流等等。

相关文章:

异步为什么会造成 HTTP 队首阻塞?

一、http 协议的队首阻塞 队首阻塞,队首的事情没有处理完的时候,后面的都要等着。 1.1 HTTP1.0 的队首阻塞 对于同一个 tcp 连接,所有的 http1.0 请求放入队列中,只有前一个请求的响应收到了,然后才能发送下一个请求。http1.0 的…...

使用hibernate,报出ORA-00933_ SQL 命令未正确结束

这里分享一个很容易出错的原因,一旦涉及到切换不同的数据源,就需要修改配置文件,有时候就会忘记了修改方言,而jpa是需要设置方言的。 比如我这里就是因为从mysql切换为了使用oracle,忘记了设置对应的方言,才…...

易点易动设备管理系统:提升企业备件管理和维修效率的智能解决方案

在当今竞争激烈的商业环境中,大型生产制造企业面临着日益复杂的设备管理挑战。为了提高生产效率和降低成本,企业需要一种高效的设备管理系统。易点易动设备管理系统是一款智能化的解决方案,旨在帮助企业提升备件管理和维修效率。本文将详细介…...

新上线游戏产品需不需要防御?

游戏运营免不了遭受恶意DDoS和CC攻击,且攻击常达百G以上,攻击流量过大,超过一般服务器的基础防护能力,不少企业面对大流量攻击显得束手无策,只能选择被迫停机,其次游戏行业利润高,很容易被黑客盯…...

Linux中的开发工具(yum,vim,gcc/g++,gdb,Makefile,git)

文章目录 1. Linux软件包管理器——yumyum 语法yum 常用命令安装 yum 仓库源 2. Linux编辑器——vimvim 的五种常用模式模式切换vim 基本操作命令模式命令集(1)光标命令(2)复制粘贴命令(3)撤销与重做&#…...

什么是自动证书管理环境(ACME)

组织的网站需要 24x7 全天候可用,以建立信任并提供信息,如果网站因证书过期而停机,那么很难恢复失去的客户信任、收入和品牌声誉,手动管理证书基础结构会使组织面临中断、中间人 (MITM) 攻击等的严重风险。…...

探索光模块的MSA多源协议

在当今高度互联的世界中,光模块作为网络设备的重要部分,其性能和质量直接影响到整个网络系统的运行。其中光模块由于其灵活性和高效性,已经成为数据中心和云计算领域的主要选择。本文易天光通信将深入探讨光模块的MSA协议,揭示其重…...

《算法通关村——双指针妙用》

《算法通关村——双指针妙用》 删除元素 描述 给你一个数组 nums 和一个值 val,你需要原地移除所有数值等于 val 的元素,并返回移除后数组的新长度。要求:不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并原地修改输入数组…...

postgresql|数据库迁移|ora2pg工具的web界面介绍

前言: ora2pg是一个比较强大的数据库迁移工具,那根据名字来说,也可以看出来,这个工具主要是用来配置去O化,将在运行的oracle数据库迁移到postgresql数据库内的 当然了,我们使用此工具主要还是用命令行&am…...

【zookeeper】zk的ZAB原子广播协议

zk的ZAB原子广播协议来源于paxos算法[1]。paxos算法是一种基于消息传递的消息一致性算法,其特点是在可靠的通信环境下,可以保证消息的最终一致性。paxos要求每台server都持有自己的一个事务id的记录,这个事务id会每通过一个提议就自增加一&am…...

【问题思考总结】为什么分布函数右连续要左闭右开

问题 这个问题困扰我很久了,虽然感觉没什么用,但是还是想着搞清楚一点。 思考 Q1:什么是右连续? A1:F(x0)F(x0),即函数在一点的右极限等于该点的函数值。 …...

解决 edge 浏览器开发者工具出不来的问题

文章目录 猜测原因问题现象尝试过程最终解决办法C盘爆满解决经过(拆东墙补西墙) 猜测原因 windows 系统更新导致电脑管家C盘迁移导致(我C盘爆满了,每天提醒看着膈应,想着清理一下) 问题现象 按F12 和 右键…...

嵌入式算法——傅里叶变换算法

文章引注 https://mp.weixin.qq.com/s/5VIpNWci9YLY3m4gcYd6-w 摘要 傅里叶变换的核心在于,“任何连续周期信号可以由一组适当的正弦曲线组合而成”,在这个基础上对信号的中特定频率的正弦波进行分解或者重组,基于频率方面分析波形。 1、傅…...

让数据“动”起来:Python动态图表制作详解

在读技术博客的过程中,我们会发现那些能够把知识、成果讲透的博主很多都会做动态图表。他们的图是怎么做的?难度大吗?这篇文章就介绍了 Python 中一种简单的动态图表制作方法。 数据暴增的年代,数据科学家、分析师在被要求对数据有…...

Python获取网络适配器接口的类型、状态IPv4和IPv6地址

参考CSDN博主「Kwoky」的https://blog.csdn.net/Kwoky/article/details/84858997的简介: psutil是一个跨平台库(http://pythonhosted.org/psutil/)能够轻松实现获取系统运行的进程和系统利用率(包括CPU、内存、磁盘、网络等)信息。它主要用来…...

无敌了!Redis进军磁盘存储!

在高手林立的数据库江湖,Redis就像一个刺客,或许不如经典数据库存在感强,但因其高性能的特质而在群英榜中独占一席。 作为缓存的首选内存数据库,Redis最近放出了一个大新闻——将磁盘作为分层存储体系结构的一部分,以…...

中文编程开发语言工具编程实际案例:台球棋牌混合计时计费软件使用的编程构件说明

中文编程开发语言工具编程实际案例:台球棋牌混合计时计费软件使用的编程构件说明 上图说明:该软件可以用于桌球和棋牌同时计时计费,在没有开台的时候,图片是处于等待状态,这使用编程工具中的固定图像构件,在…...

在线客服系统源码 客服系统源码

在线客服系统源码 客服系统源码 框架:Thinkphp5workerman,环境:nginxphp7.3mysql5.6 多商户客服、不限坐席、独立系统--数据存储自己服务器上,支持开启SSL、支持离线对话。 新款在线客服系统全开源无加密:多商户、国…...

抽象轻松java——简易图书馆前置

用Maven写一个垃圾的项目&#xff0c;第一步打开IDEA&#xff0c;点击创建&#xff0c;创建一个Maven <dependencies><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.22</versi…...

图书推荐管理系统Python+Django网页界面+协同过滤推荐算法

一、介绍 图书管理与推荐系统。使用Python作为主要开发语言。前端采用HTML、CSS、BootStrap等技术搭建界面结构&#xff0c;后端采用Django作为逻辑处理&#xff0c;通过Ajax等技术实现数据交互通信。在图书推荐方面使用经典的协同过滤算法作为推荐算法模块。主要功能有&#…...

Golang dig框架与GraphQL的完美结合

将 Go 的 Dig 依赖注入框架与 GraphQL 结合使用&#xff0c;可以显著提升应用程序的可维护性、可测试性以及灵活性。 Dig 是一个强大的依赖注入容器&#xff0c;能够帮助开发者更好地管理复杂的依赖关系&#xff0c;而 GraphQL 则是一种用于 API 的查询语言&#xff0c;能够提…...

基于当前项目通过npm包形式暴露公共组件

1.package.sjon文件配置 其中xh-flowable就是暴露出去的npm包名 2.创建tpyes文件夹&#xff0c;并新增内容 3.创建package文件夹...

镜像里切换为普通用户

如果你登录远程虚拟机默认就是 root 用户&#xff0c;但你不希望用 root 权限运行 ns-3&#xff08;这是对的&#xff0c;ns3 工具会拒绝 root&#xff09;&#xff0c;你可以按以下方法创建一个 非 root 用户账号 并切换到它运行 ns-3。 一次性解决方案&#xff1a;创建非 roo…...

学习STC51单片机31(芯片为STC89C52RCRC)OLED显示屏1

每日一言 生活的美好&#xff0c;总是藏在那些你咬牙坚持的日子里。 硬件&#xff1a;OLED 以后要用到OLED的时候找到这个文件 OLED的设备地址 SSD1306"SSD" 是品牌缩写&#xff0c;"1306" 是产品编号。 驱动 OLED 屏幕的 IIC 总线数据传输格式 示意图 …...

Spring AI与Spring Modulith核心技术解析

Spring AI核心架构解析 Spring AI&#xff08;https://spring.io/projects/spring-ai&#xff09;作为Spring生态中的AI集成框架&#xff0c;其核心设计理念是通过模块化架构降低AI应用的开发复杂度。与Python生态中的LangChain/LlamaIndex等工具类似&#xff0c;但特别为多语…...

什么是Ansible Jinja2

理解 Ansible Jinja2 模板 Ansible 是一款功能强大的开源自动化工具&#xff0c;可让您无缝地管理和配置系统。Ansible 的一大亮点是它使用 Jinja2 模板&#xff0c;允许您根据变量数据动态生成文件、配置设置和脚本。本文将向您介绍 Ansible 中的 Jinja2 模板&#xff0c;并通…...

CSS设置元素的宽度根据其内容自动调整

width: fit-content 是 CSS 中的一个属性值&#xff0c;用于设置元素的宽度根据其内容自动调整&#xff0c;确保宽度刚好容纳内容而不会超出。 效果对比 默认情况&#xff08;width: auto&#xff09;&#xff1a; 块级元素&#xff08;如 <div>&#xff09;会占满父容器…...

PAN/FPN

import torch import torch.nn as nn import torch.nn.functional as F import mathclass LowResQueryHighResKVAttention(nn.Module):"""方案 1: 低分辨率特征 (Query) 查询高分辨率特征 (Key, Value).输出分辨率与低分辨率输入相同。"""def __…...

接口自动化测试:HttpRunner基础

相关文档 HttpRunner V3.x中文文档 HttpRunner 用户指南 使用HttpRunner 3.x实现接口自动化测试 HttpRunner介绍 HttpRunner 是一个开源的 API 测试工具&#xff0c;支持 HTTP(S)/HTTP2/WebSocket/RPC 等网络协议&#xff0c;涵盖接口测试、性能测试、数字体验监测等测试类型…...

MySQL 主从同步异常处理

阅读原文&#xff1a;https://www.xiaozaoshu.top/articles/mysql-m-s-update-pk MySQL 做双主&#xff0c;遇到的这个错误&#xff1a; Could not execute Update_rows event on table ... Error_code: 1032是 MySQL 主从复制时的经典错误之一&#xff0c;通常表示&#xff…...