(六) HTTP/2流的优先级

本文详细介绍了HTTP/2中流的优先级管理,包括流依赖、权重、优先级调整和状态管理。通过设置优先级,端点可以指导资源分配,尤其是在发送能力受限时。依赖权重用于决定资源分配比例,而PRIORITY帧则用于改变流的优先级。当流被关闭时,其从属流会根据权重重新分配优先级。默认情况下,所有流依赖于不存在的“流0”,并拥有默认权重16。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

客户端可以通过在打开流的HEADERS帧中包含优先次序信息来为一个新流指定优先级。在其它任意时间,可以使用PRIORITY帧来改变流的优先级。

优先次序的目的是允许端点表达希望对端在管理并发流的时候如何分配资源。更重要的是,当发送能力受限的时候,优先级能够用来选择流发送帧。

通过让流依赖其它流的完成,可以为流排列优先级。每个依赖都被分配了一个相对权重,即一个用来决定分配给依赖相同流的各个流的可用资源相对比例的数字。

显式地为一个流设置优先级是对一个优先级处理过程的输入,它不能保证这个流相对于其它流具有任何特定的处理和传输顺序。一个端点不能强迫对端使用优先级按照特定的顺序处理并发的多个流。因此,优先级的表达仅仅是一个建议。

优先级信息可以从消息中省略。如果没有提供优先级,那么就使用默认的优先级。

流依赖

每个流都可以显式地依赖其它流。依赖表达了希望优先分配资源给被依赖的流,而不是依赖其它流的流。

不依赖任何其它流的流被分配了值为0x0的依赖。也就是说,实际上并不存在的“流0”构成了依赖树的树根。

一个依赖其它流的流是“从属流”。一个被其它流依赖的流是“父亲流”。依赖当前树中不存在的流(例如,流的状态是“空闲”)会导致流被赋予默认的优先级。当依赖其它流时,当前的这个流就被添加为父亲流的一个新的依赖。共享相同的父亲流的各个从属流之间并没有固定的排序。例如,如果流B和流C依赖流A,并且,新创建的流D也依赖流A,那么结果就是,流A同时被流B、C和D依赖,但是,流B、C和D之间并没有确定的顺序。过程如下图所示:

       A                 A
      / \      ==>      /|\
     B   C             B D C

“排他”标识允许插入一个新的层级的依赖。“排他”标识导致新插入的流成为它的“父亲流”的唯一“从属流”,而“父亲流”原来的其它“从属流”变成了新插入流的“从属流”。在前面的例子中,如果新创建的流D(具有“排他”标识)依赖流A,那么,流D就变成了流B和流C所依赖的“父亲流”。过程如下图所示:

                         A
       A                 |
      / \      ==>       D
     B   C              / \
                       B   C

在依赖树中,只有在以下情况下才应该给“从属流”分配资源:该“从属流”依赖的所有流都已经被关闭或者无法取得进展。(这里的“所有流”包括从父亲流一直向上到达树根所经过的路径中的所有流,也就是当前流在依赖树中的所有“祖先流”)

一个流不能依赖它自己。客户端或服务端必须将这种情况视为类型为PROTOCOL_ERROR的流错误。

依赖权重

所有“从属流”都被分配了1到256之间的一个整数权重。

依赖相同“父亲流”的多个“从属流”应该按照权重比例被分配资源。因此,如果流B依赖流A,权重是4;流C依赖流A,权重是12,并且,流A没有任何进展,那么,理论上流B获取的资源相当于流C的三分之一。

调整优先级

使用PRIORITY帧可以改变流的优先级。设置一个依赖将导致一个流变得依赖某个特定的“父亲流”。

如果“父亲流”的优先级被重新调整,那么“从属流”们跟随它们的“父亲流”一起在依赖树中移动。为一个重新调整优先级的流设置一个具有“排他”标识的依赖,会导致所有之前依赖新的“父亲流”的“从属流”变为依赖调整优先级的流的“从属流”。

如果一个流被设置为依赖它的一个“从属流”,那么,这个“从属流”首先被调整为依赖它的前任“父亲流”的“父亲流”。被移动的依赖保持它们的权重不变。

举个例子吧,最初的依赖树中,流B和流C依赖流A,流D和流E依赖流C,流F依赖流D。如果A被改为依赖D,那么D取代A的位置。所有其它依赖关系保持不变,但F是个例外,如果调整优先级时使用了“排他”标识,那么F最终变为依赖A。调整过程如下图所示:

       x                x                x                 x
       |               / \               |                 |
       A              D   A              D                 D
      / \            /   / \            / \                |
     B   C     ==>  F   B   C   ==>    F   A       OR      A
        / \                 |             / \             /|\
       D   E                E            B   C           B C F
       |                                     |             |
       F                                     E             E
                     (中间步骤)          (非排他)           (排他)

优先级状态管理

如果一个流被从依赖树中移除,那么它的“从属流”们被调整为依赖被关闭流的“父亲流”(被关闭的流就是被移除的那个流)。新的依赖的权重被重新计算:基于被关闭流的“从属流”们的权重比例,将被关闭流的权重分配给它的“从属流”们。

从依赖树中移除流会导致一些优先级信息丢失。资源在具有相同“父亲流”的多个“从属流”之间共享,这意味着,如果其中一个“从属流”关闭或被阻塞,那么,分配给它的任何空闲容量都会被重新分发给它的最近“邻居流”。然而,如果公共依赖(父亲流)被从树中移除,那么,这些“从属流”就与更高一层的流共享资源。

例如,假设流A和流B共享一个父亲流,流C和流D都依赖流A。在流A被移除之前,如果流A和流D无法继续处理,那么流C就会接收所有投入给流A的资源。如果流A从树中移除,流A的权重将分配给流C和流D。如果流D仍然无法继续处理,将导致流C获取的资源比例降低。对于相同的初始权重,流C获取到三分之一,而不是二分之一的可用资源。

有可能创建依赖的优先级信息还在传输过程中,流就已经关闭了。如果在依赖中标识的一个流没有关联的优先级信息,那么依赖它的从属流将被分配一个默认的优先级。这有可能创建不理想的优先级,因为流可能被分配一个不符合预期的优先级。

为了避免这种问题,端点应该在流关闭以后的一段时间内保持流的优先级状态。状态的保存时间越长,流被分配错误或默认的优先级的机会就越少。

类似地,处于空闲状态的流也可以被分配优先级或者成为其它流的“父亲流”。这允许在依赖树中创建一组节点,从而提供更加灵活的优先级表现形式。空闲的流以一个默认的优先级开始。

为未达到SETTINGS_MAX_CONCURRENT_STREAMS参数最大限制的流们保留优先级信息可能会增加端点的负担。因此,可以限制保留的优先级状态信息的数量。

端点为优先级维护的附加状态的数量可以依赖自身的负载而设置。在高负载下,优先级状态可以被丢弃,以限制资源的承诺。在极端情况下,端点甚至可以丢弃处于激活状态或保留状态的流的优先级信息。如果应用了限制,端点应该维护的状态数量至少不能低于SETTINGS_MAX_CONCURRENT_STREAMS中设置的值。具体的实现应该也尝试保留优先级树中活跃使用的流的状态。

如果保留了足够的状态的话,当接收到修改一个关闭流的优先级的PRIORITY帧时,端点应该修改依赖树中这个流的“从属流”的优先级。

默认优先级

所有的流最初都被设置为“非排他”地依赖流0x0。“推送流”最初依赖它们的“关联流”。在这两种情况下,流被分配默认的优先级,值为16。

<think>嗯,用户之前问过面试中常见的计算机网络知识点,现在他们又具体问到了HTTP/1.1和HTTP/2的主要区别。这说明用户可能在准备面试,特别是针对HTTP协议的深入问题。我需要先回顾一下这两个版本的核心差异,确保信息准确且易于理解。 首先,用户可能已经了解HTTP的基础,比如无状态、请求-响应模型等,所以他们需要更高级的比较。我记得HTTP/2的几个关键改进点:多路复用、头部压缩、服务器推送和二进制协议。而HTTP/1.1的问题在于队头阻塞、多次TCP连接和文本格式导致的低效。 用户可能想知道这些改进如何解决HTTP/1.1的痛点,比如页面加载速度慢的问题。需要具体说明每个改进点,比如多路复用如何在一个连接上处理多个请求,避免建立多个连接的开销。头部压缩使用HPACK算法减少冗余,提高传输效率。 另外,HTTP/2的服务器推送可能是一个容易被忽略但重要的点,需要解释清楚其用途和优势。用户可能还会关心兼容性,比如HTTP/2是否必须使用HTTPS,实际上虽然不是强制,但主浏览器都只支持加密连接下的HTTP/2。 同时,用户可能希望了解这些变化对实际开发的影响,比如是否需要改变现有的代码结构,或者如何利用新特性优化应用。需要指出虽然HTTP/2优化了传输效率,但应用层API保持不变,开发者无需大幅修改代码。 还要注意回答的结构,分点对比更清晰,可能用户需要记忆这些区别,所以用表格或者列表形式比较好。同时,补充示例,比如HTTP/1.1的队头阻塞问题,如何通过多路复用解决,帮助用户更直观地理解。 最后,确保回答覆盖了常见的面试问题,比如为什么HTTP/2更高效,解决了哪些问题,以及潜在的缺点或挑战。例如,虽然HTTP/2解决了应用层队头阻塞,但TCP层的队头阻塞仍然存在,这可能引向HTTP/3的QUIC协议,但用户可能现在只关注HTTP/2,所以点到为止即可。 总结来说,回答需要结构清晰,对比明确,技术点准确,同时结合实际应用场景,帮助用户理解这些改进的实际意义,而不仅仅是理论上的区别。</think>好的!HTTP/1.1 和 HTTP/2 的核心区别主要体现在 **性能优化** 和 **协议设计理念** 上。以下是具体对比: --- ### **一、核心设计差异** | **特性** | **HTTP/1.1** | **HTTP/2** | |-------------------|-------------------------------|--------------------------------| | **传输方式** | 文本格式(明文传输) | 二进制格式(更高效、更安全) | | **连接复用** | 需多个TCP连接(并行有限) | 单一TCP连接支持多路复用 | | **头部压缩** | 无压缩,重复头部浪费带宽 | 使用HPACK算法压缩头部 | | **服务器推送** | 不支持 | 支持主动推送资源(如CSS/JS) | | **优先级控制** | 无 | 可设置请求优先级 | --- ### **二、关键改进解析** #### 1. **多路复用(Multiplexing)** - **HTTP/1.1问题**: - 每个请求需独立TCP连接(默认6-8个并发限制)。 - 队头阻塞(Head-of-Line Blocking):前一个请求未完成会阻塞后续请求。 ```plaintext # 示例:加载页面需多个资源时,需排队等待 请求A → 响应A → 请求B → 响应B → ... ``` - **HTTP/2解决方案**: - 单个TCP连接上并行传输多个请求/响应(通过二进制帧拆分数据)。 - 避免队头阻塞,提升页面加载速度。 #### 2. **头部压缩(Header Compression)** - **HTTP/1.1问题**: - 每次请求需携带大量重复头部(如`User-Agent`、`Cookie`)。 - 浪费带宽(尤其移动端场景)。 - **HTTP/2解决方案**: - 使用`HPACK`算法压缩头部: - 维护静态表(预定义常见头部字段)和动态表(自定义字段)。 - 通过索引替换重复字段,减少冗余传输。 #### 3. **服务器推送(Server Push)** - **HTTP/1.1问题**: - 客户端需主动请求所有资源(如HTML解析后才请求CSS/JS)。 - **HTTP/2解决方案**: - 服务器可主动推送客户端可能需要的资源(如关联的CSS文件)。 - 减少往返延迟(RTT),加速页面渲染。 #### 4. **二进制分帧(Binary Framing)** - **HTTP/1.1**:基于文本解析,易出错且效率低(如换行符处理)。 - **HTTP/2**: - 将消息拆分为二进制帧(`HEADERS`帧、`DATA`帧等)。 - 支持乱序传输与重组,提升传输灵活性。 --- ### **三、性能对比示例** 假设加载一个包含10个资源的页面: - **HTTP/1.1**: - 建立6个TCP连接(默认并发限制),剩余资源需排队。 - 总时间 ≈ 多次RTT(往返延迟) + 资源传输时间。 - **HTTP/2**: - 1个TCP连接内并行传输所有资源。 - 总时间 ≈ 1次RTT(握手) + 资源传输时间(无排队)。 --- ### **四、其他改进** 1. **优先级**: - HTTP/2允许为资源设置优先级(如优先加载HTML而非图片)。 2. **更安全的默认配置**: - 主浏览器要求HTTP/2必须基于HTTPS(实际非强制,但行业约定)。 --- ### **五、需要注意的“伪改进”** - **底层TCP限制**: HTTP/2仍基于TCP,若发生丢包,所有会被阻塞(TCP队头阻塞)。 (注:HTTP/3改用QUIC协议解决此问题,基于UDP) --- ### **、面试常见问题** 1. **为什么HTTP/2HTTP/1.1快?** → 多路复用减少连接数 + 头部压缩减少冗余数据 + 服务器推送预加载资源。 2. **HTTP/2是否必须使用HTTPS?** → 协议未强制,但Chrome/Firefox等浏览器仅支持HTTPS下的HTTP/2。 3. **HTTP/2如何解决队头阻塞?** → 应用层多路复用,但传输层仍依赖TCP(未彻底解决)。 --- **总结**:HTTP/2 通过二进制分帧、多路复用等技术,显著提升了传输效率和页面加载速度,但对开发者透明(无需修改API),是HTTP/1.1的平滑升级。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值