什么是队头阻塞以及如何解决

HTTP2解决了http1.1中管道化队头阻塞问题:

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

=======================================================

 

前言

通常我们提到队头阻塞,指的可能是TCP协议中的队头阻塞,但是HTTP1.1中也有一个类似TCP队头阻塞的问题,下面各自介绍一下。

TCP队头阻塞

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

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

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

HTTP队头阻塞

上面用浏览器请求图片资源举例子,但实际上HTTP自身也有类似TCP队头阻塞的情况。要介绍HTTP队头阻塞,就需要先讲讲HTTP的管道化(pipelining)。

HTTP管道化是什么

HTTP1.1 允许在持久连接上可选的使用请求管道。这是相对于keep-alive连接的又一性能优化。在相应到达之前,可以将多条请求放入队列,当第一条请求发往服务器的时候,第二第三条请求也可以开始发送了,在高延时网络条件下,这样做可以降低网络的环回时间,提高性能。

非管道化与管道化的区别示意

 

 

HTTP管道化产生的背景

在一般情况下,HTTP遵守“请求-响应”的模式,也就是客户端每次发送一个请求到服务端,服务端返回响应。这种模式非常容易理解,但是效率并不是那么高,为了提高速度和效率,人们做了很多尝试:

  • 最简单的情况下,服务端一旦返回响应后就会把对应的连接关闭,客户端的多个请求实际上是串行发送的。
  • 除此之外,客户端可以选择同时创建多个连接,在多个连接上并行的发送不同请求。但是创建更多连接也带来了更多的消耗,当前大部分浏览器都会限制对同一个域名的连接数。
  • 从HTTP1.0开始增加了持久连接的概念(HTTP1.0的Keep-Alive和HTTP1.1的persistent),可以使HTTP能够复用已经创建好的连接。客户端在收到服务端响应后,可以复用上次的连接发送下一个请求,而不用重新建立连接。
  • 现代浏览器大多采用并行连接与持久连接共用的方式提高访问速度,对每个域名建立并行地少量持久连接。
  • 而在持久连接的基础上,HTTP1.1进一步地支持在持久连接上使用管道化(pipelining)特性。管道化允许客户端在已发送的请求收到服务端的响应之前发送下一个请求,借此来减少等待时间提高吞吐;如果多个请求能在同一个TCP分节发送的话,还能提高网络利用率。但是因为HTTP管道化本身可能会导致队头阻塞的问题,以及一些其他的原因,现代浏览器默认都关闭了管道化。

HTTP管道化的限制

  1. 管道化要求服务端按照请求发送的顺序返回响应(FIFO),原因很简单,HTTP请求和响应并没有序号标识,无法将乱序的响应与请求关联起来。
  2. 客户端需要保持未收到响应的请求,当连接意外中断时,需要重新发送这部分请求。
  3. 只有幂等的请求才能进行管道化,也就是只有GET和HEAD请求才能管道化,否则可能会出现意料之外的结果

HTTP管道化引起的请求队头阻塞

前面提到HTTP管道化要求服务端必须按照请求发送的顺序返回响应,那如果一个响应返回延迟了,那么其后续的响应都会被延迟,直到队头的响应送达。

如何解决队头阻塞

如何解决HTTP队头阻塞

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

当然,即使使用HTTP2,如果HTTP2底层使用的是TCP协议,仍可能出现TCP队头阻塞。

如何解决TCP队头阻塞

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

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

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

总结

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

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

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

<think>嗯,用户现在问的是HTTP/2中的队头阻塞和冗余头部是什么意思。之前他们问过HTTP/2是否是主流,我详细介绍了普及情况、优势以及和HTTP/1.1的共存情况。现在他们想深入了解这两个技术术语,可能需要更基础的解释。 首先,用户可能不太清楚HTTP/2的具体工作原理,特别是相对于HTTP/1.1的改进。队头阻塞HTTP/1.1中是一个大问题,但HTTP/2虽然解决了应用层的队头阻塞,但在传输层仍然存在,这点需要明确解释。用户可能混淆了这两个层面的问题。 冗余头部可能是指HTTP/1.1中每个请求都发送大量重复的头部信息,而HTTP/2通过HPACK压缩解决了这个问题。用户可能想知道具体是怎么压缩的,比如静态字典、动态编码这些机制,但需要避免过于技术化的术语,用简单例子说明。 此外,用户可能在实际开发或学习中遇到了相关的问题,比如网站性能优化,想知道HTTP/2如何帮助减少延迟和带宽。可能需要结合之前的回答,强调HTTP/2的优势,同时指出其局限性,比如TCP层的队头阻塞,为引入HTTP/3做铺垫。 要确保解释清晰,分点说明,使用例子帮助理解。例如,用多个文件请求的例子说明多路复用如何解决队头阻塞,用头部字段如User-Agent重复发送的例子说明冗余问题。同时,比较HTTP/1.1和HTTP/2的不同,突出改进之处。 还要注意用户可能的深层需求,比如是否应该升级到HTTP/2或HTTP/3,但当前问题集中在理解这两个概念上,所以回答要聚焦,不过可以稍微提到HTTP/3的进一步优化,作为扩展知识。</think>好的!以下是关于 HTTP/2 中**队头阻塞(Head-of-Line Blocking)**和**冗余头部(Redundant Headers)**的通俗解释: --- ### **一、HTTP/2 的队头阻塞问题** #### **1. 什么是队头阻塞?** 队头阻塞是指一个请求/响应被延迟处理时,导致后续请求/响应必须等待的现象。这种现象在 HTTP/1.1 中尤为明显,而 HTTP/2 虽然优化了部分问题,但未完全消除。 #### **2. HTTP/1.1 的队头阻塞** - **HTTP/1.1 的串行传输**: 浏览器对同一域名下最多允许 6~8 个 TCP 连接,但每个连接上的请求必须按顺序处理。 **例子**:如果请求 A 的响应未完成,后续请求 B、C 即使资源已准备好,也必须排队等待。 #### **3. HTTP/2 的改进与局限性** - **多路复用(Multiplexing)**: HTTP/2 允许在**单个 TCP 连接**上并发传输多个请求/响应(称为“流”),解决HTTP/1.1 的应用层队头阻塞。 **例子**:请求 A、B、C 可同时传输,无需等待彼此。 - **TCP 层的队头阻塞**: 由于 HTTP/2 仍基于 TCP 协议,若 TCP 数据包在传输中丢失或延迟,后续所有流(即使已到达)必须等待该包重传,导致**传输层队头阻塞**。 **影响**:在高丢包率的网络(如移动网络)中,性能可能下降。 --- ### **二、冗余头部(Redundant Headers)** #### **1. HTTP/1.1 的头部冗余问题** - **重复传输**: HTTP/1.1 的每个请求必须携带完整的头部信息(如 `User-Agent`、`Cookie` 等),即使这些字段与前一个请求完全相同。 **例子**:连续请求 10 张图片时,相同的 `User-Agent` 字段会被重复发送 10 次,浪费带宽。 #### **2. HTTP/2 的优化:HPACK 压缩** - **静态字典 + 动态编码**: HTTP/2 使用 HPACK 算法压缩头部: - **静态字典**:预定义常见头部字段(如 `:method: GET`),用简短数字代替文本。 - **动态字典**:针对当前连接,动态缓存新出现的头部字段(如 `Cookie: abc`),后续请求复用缓存索引。 - **效果**: 典型场景下,头部大小可减少 **50%~90%**。例如,原本 500 字节的头部,压缩后可能仅需 50 字节。 #### **3. 示例对比** - **HTTP/1.1 请求**: ```http GET /image.jpg HTTP/1.1 Host: example.com User-Agent: Chrome/120 Cookie: session=abc123 Accept: image/webp ``` 每次请求都需要重复发送所有头部字段。 - **HTTP/2 请求**: - 首次请求:压缩后头部占用 100 字节。 - 后续请求:仅需发送动态字典中的索引(如 `62` 代表 `User-Agent: Chrome/120`),可能仅需 20 字节。 --- ### **三、总结** | **问题** | **HTTP/1.1 的表现** | **HTTP/2 的优化** | |--|-------------------------------------------| | **队头阻塞** | 应用层严重阻塞(请求串行) | 解决应用层阻塞,但 TCP 层仍存在潜在阻塞 | | **冗余头部** | 每次请求重复发送完整头部 | 通过 HPACK 压缩大幅减少冗余数据 | #### **扩展知识** - **HTTP/3 的进一步优化**: 基于 QUIC 协议(UDP),彻底解决 TCP 层队头阻塞,并优化头部压缩算法(QPACK)。但 HTTP/2 仍是当前主流选择。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值