技术知识文章集合TECHNICAL ARCHIVE · 457 DOCUMENTS

显示模式

登录
ARCHIVE DOCUMENTNET

解密 HTTP/2 与 HTTP/3 的新特性

所属馆藏
NET Protocol
文件格式
Markdown
原始路径
NET Protocol/28-解密HTTP 2与HTTP 3的新特性
本文目录8 个章节
  1. HTTP/1.1 发明以来发生了哪些变化?
  2. 一、HTTP/1.1 的常见问题
  3. 二、SPDY 协议与 HTTP/2 简介
  4. 三、HTTP/2 的新特性
  5. 四、HTTP/3 的背景与新特性
  6. 五、HTTP/2 与 HTTP/3 的对比
  7. 六、总结
  8. 参考资料

解密 HTTP/2 与 HTTP/3 的新特性

Category(分类): NET Protocol Status: 未知

HTTP/2 相比 HTTP/1.1 在二进制分帧、首部压缩和多路复用等方面进行了改进,通常可以减少请求排队和重复首部带来的开销。但 HTTP/2 并不是在所有场景下都一定更快,也不能完全替代前端性能优化。HTTP/3 则将 HTTP 语义运行在 QUIC 之上,主要解决 HTTP/2 依赖 TCP 时产生的连接级队头阻塞,并提供连接迁移等能力。

HTTP/1.1 发明以来发生了哪些变化?

如果观察某一时期流行网站首页需要下载的资源,会发现页面资源数量和传输数据量都曾经持续增长。原文引用的统计图显示,在特定样本和时间范围内,页面传输数据量曾超过 2100 KB,平均资源数量也曾超过 100 个。

这些数字属于特定时期和统计样本,不能直接当作今天所有网页的普遍数据。不过,网页从早期以文本为主逐渐发展为包含图片、音频、视频和实时交互内容的富媒体应用,确实对协议的连接复用、传输效率和安全性提出了更高要求。

网页资源数量和传输数据量变化示意图

HTTP/1.1 于 1997 年发布,长期以来一直被广泛使用。随着页面资源数量增加,HTTP/1.1 在高延迟网络和大量小资源场景下的局限逐渐显现,HTTP/2 和 HTTP/3 因此得到发展。

一、HTTP/1.1 的常见问题

HTTP/1.1 本身并不是不可用的协议,但在大量小资源、较高 RTT 或存在丢包的网络环境中,以下问题可能限制性能:

  1. 同一连接上的请求排队和队头阻塞;
  2. 缺少通用的动态首部压缩,重复首部带来额外开销;
  3. HTTP 协议本身不提供加密和身份认证;
  4. 没有 HTTP/2 那样的标准服务器推送流机制。

1. 高延迟与队头阻塞

网络带宽增长并不意味着网络延迟会同比降低。网络延迟还会受到物理距离、路由、拥塞、DNS、连接建立和服务器处理时间等多种因素影响。HTTP/1.1 中,同一持久连接上的请求可能需要排队,队首请求没有完成时,后续响应也可能受到影响,这就是应用层的队头阻塞(Head-of-Line Blocking,HOL Blocking)。

HTTP/1.1 队头阻塞示意图

HTTP/1.1 支持管道化(pipelining),客户端可以在没有收到前一个响应时继续发送后续请求,但响应必须按照请求顺序返回,队首响应延迟仍会阻塞后续响应。由于中间设备和浏览器对管道化的支持、兼容性和部署体验不理想,现代浏览器通常更多使用多个持久连接提高并发度。

旧版浏览器常见的做法是限制同一主机的并发连接数,例如曾经常见的 6 个连接。但具体数量会随浏览器、协议版本、代理和配置变化,不能当作固定标准。HTTP/2 和 HTTP/3 通常可以在一个连接上复用多个流,也不应继续把“同域名固定 6 个连接”作为现代浏览器规则。

为了缓解 HTTP/1.1 下的请求排队,过去常见的做法包括:

  • 域名分片:将资源分散到不同域名,以绕过单个主机的连接数限制。但在 HTTP/2 和 HTTP/3 中,域名分片可能破坏连接复用,增加握手和拥塞控制开销,需要根据实际情况评估。
  • Spriting(雪碧图):将多张小图合并为一张大图,再通过 CSS 或 JavaScript 定位使用,可以减少请求数,但会降低资源缓存的粒度。
  • 内联(Inlining):将小图片等资源编码后嵌入 CSS、HTML 或脚本中,减少请求次数,但可能增大主文档并影响缓存。

例如,图片可以以内联数据的形式写入 CSS:

.icon1 {
  background: url(data:image/png;base64,<data>) no-repeat;
}

.icon2 {
  background: url(data:image/png;base64,<data>) no-repeat;
}
  • 拼接(Concatenation):将多个较小的 JavaScript 文件打包为一个文件,可以减少请求数。但其中一个文件发生修改时,整个合并文件可能需要重新下载。现代构建工具通常会结合代码分割和长期缓存使用。

这些优化是特定网络条件下的工程手段,并不是所有项目都应该无条件采用。

2. 无状态语义与首部开销

HTTP 的无状态性是指每个请求在语义上相对独立,服务器不能只依赖上一个请求来理解当前请求。这并不意味着每个请求都要新建 TCP 连接:HTTP/1.1 默认支持持久连接,同一 TCP 连接可以承载多个请求。

请求头中的 User-AgentCookieAccept 等字段,以及响应头中的 Cache-ControlContent-TypeServer 等字段,可能在很多报文中重复出现。对于请求体很小的场景,首部占比可能较高,从而增加传输成本。

需要注意,Server 通常是响应头,不应作为请求头示例。204 No Content304 Not Modified 按规范不能包含响应内容,301 响应则可以包含可选的响应内容,因此不能把它们都简单归类为“只有几十字节的响应”。

HTTP/1.1 没有像 HTTP/2 的 HPACK、HTTP/3 的 QPACK 那样的通用动态首部压缩机制,因此重复首部的开销更明显。Cookie 还可能随着业务信息增加而变大,实际应用中应控制 Cookie 的数量和大小。

HTTP/1.1 首部开销示意图

3. HTTP 本身不提供加密

HTTP/1.1 的协议语义本身不提供加密、完整性保护和身份认证。直接使用 http:// 时,网络中的攻击者可能窃听或篡改内容,也无法通过 HTTP 本身确认服务器身份。

例如,公共 Wi-Fi 环境中的攻击者可能通过伪造热点或中间人攻击观察未加密的 HTTP 流量。如果请求中包含密码、令牌等敏感信息,就可能造成泄露。

HTTP/1.1 也可以运行在 TLS 之上,即 HTTPS。HTTPS 通过 TLS 提供加密、完整性保护,并通常验证服务器证书。因此,不能简单地说所有 HTTP/1.1 都是明文,应区分 HTTP 协议语义和承载它的 TLS 连接。

4. 没有标准化的服务器推送

HTTP/1.1 没有 HTTP/2 那样的标准服务器推送流机制。服务器可以使用缓存预热、Link: preload、103 Early Hints 等方式帮助客户端提前发现资源,但这些机制与 HTTP/2 Server Push 并不完全相同。

二、SPDY 协议与 HTTP/2 简介

1. SPDY 协议

由于 HTTP/1.x 在高延迟网络中存在请求排队和首部重复等问题,Google 在 2009 年公开了 SPDY 协议。SPDY 在 HTTP 语义之下引入了二进制分帧、流复用、首部压缩和优先级等机制,通常运行在 TCP 和 TLS 之上。

SPDY 与 HTTP/2 的关系示意图

SPDY 的实践验证了这些设计思路的可行性,后来 HTTP/2 吸收了其中很多特性。SPDY 本身已经退出历史舞台,现代实现主要使用 HTTP/2 或 HTTP/3。

HTTP/1.1 的主要问题可以概括为性能和安全方面的局限。由于 HTTP/1.x 背负着庞大的历史包袱,协议升级需要考虑兼容性,否则可能影响互联网上已有的大量客户端、服务器和中间设备。

2. HTTP/2 简介

HTTP/2 于 2015 年以 RFC 7540 的形式发布。当前 HTTP/2 的主要规范是 RFC 9113,HPACK 仍由 RFC 7541 定义。

HTTP/2 不是把 HTTP 语义完全重写,而是尽量保留 HTTP 方法、状态码、请求头、响应头和内容等语义,同时改变线上报文的传输格式。HTTP/2 的二进制帧格式与 HTTP/1.1 的文本报文格式并不兼容,需要通过 ALPN、Upgrade 或其他协商方式确定协议版本。

HTTP/2 的主要目标之一是允许同一连接承载多个并发请求和响应,但协议并不强制每个 origin 只能建立一个连接。客户端和服务器仍可能因为并发流限制、连接策略、故障隔离或其他原因使用多个连接。

HTTP/2 的性能收益没有统一固定值,实际效果取决于网络 RTT、丢包率、资源数量、资源大小、缓存、服务器配置和客户端实现。

三、HTTP/2 的新特性

1. 二进制分帧

HTTP/2 使用二进制帧传输协议控制信息和 HTTP 消息,不再直接传输 HTTP/1.1 那样的文本请求行和首部行。二进制格式主要有利于解析、边界识别和多路交错传输,并不意味着所有数据都会因为二进制编码而自动变小。

HTTP/2 常见的帧包括:

  • HEADERS:传输首部块;
  • CONTINUATION:延续较大的首部块;
  • DATA:传输请求或响应内容;
  • SETTINGS:协商连接参数;
  • WINDOW_UPDATE:更新流量控制窗口;
  • RST_STREAM:终止单个流。

一个请求或响应可以由一个或多个消息部分组成,消息由一个或多个帧承载。帧带有流标识符,来自不同流的帧可以在同一个 TCP 连接中交错发送;但是同一个流中的帧仍需要按顺序处理,首部块中的 CONTINUATION 帧也必须保持规定的连续顺序。

HTTP/2 仍然保留 HTTP 的首部和内容语义,只是将这些信息拆分到不同的二进制帧中,并不意味着“Header + Body”在语义上完全消失。

HTTP/2 二进制分帧示意图

2. HPACK 首部压缩

HTTP/2 使用 HPACK 压缩首部。HPACK 不是简单地对每个请求独立使用 gzip,而是让编码端和解码端维护静态表和动态表,并用索引引用重复的首部字段。

HPACK 主要包括:

  • 静态表:预先定义常见的首部名称和值;
  • 动态表:连接过程中根据已发送的首部字段逐步更新,并受到表大小限制;
  • 索引表示:直接引用表中的字段;
  • 字面量表示:直接发送新的字段名称或值,可以选择是否加入动态表;
  • Huffman 编码:可用于压缩字符串字面量,整数使用 HPACK 定义的变长整数编码。

动态表并不是永久不变的字典。新条目可能被插入,旧条目可能因为容量限制被逐出,编码端还可以选择不索引敏感字段。首部压缩比例取决于请求的重复程度和字段大小,没有固定的“50%~90%”保证。

HTTP/2 HPACK 首部压缩示意图

3. 多路复用

HTTP/2 在一个连接中引入多个独立的流。每个请求/响应通常对应一个流,流中的消息被拆成帧后,可以与其他流的帧交错发送。这样可以减少 HTTP/1.1 中为提高并发而建立多个 TCP 连接的需要,并且通常只需要进行一次 TCP 慢启动和一次 TLS 建立。

HTTP/2 的多路复用具有以下特点:

  • 一个连接可以承载多个双向流,但并发流数量受 SETTINGS_MAX_CONCURRENT_STREAMS 等参数限制;
  • 一个流的 HTTP 层响应不必等待另一个流的响应完成;
  • 连接级流量控制和流级流量控制共同限制发送量;
  • 服务器仍需要根据资源、优先级和负载对各个流进行调度;
  • TCP 仍然是单一有序字节流,因此 TCP 丢包会影响该连接中多个流的数据交付。

HTTP/2 多路复用演示

原文曾使用 Akamai 的 HTTP/2 演示链接展示 HTTP/2 与 HTTP/1.1 的差异:https://http2.akamai.com/demo。该链接属于历史演示,是否仍可访问取决于服务状态,实际性能应以当前项目的真实测试为准。

多路复用通常可以减少连接数和握手开销,但不代表所有请求都能无限并行,也不代表不同流之间完全互不影响。服务器处理能力、连接级窗口、拥塞控制和 TCP 队头阻塞仍然会造成相互影响。

HTTP/2 优先级

早期 HTTP/2 使用流依赖关系和权重表达优先级。传统优先级机制包含流依赖关系、独占标志和 1~256 的权重,并不是“每个请求拥有一个 31 位优先值,数值越小越优先”。

当前 RFC 9113 已经弃用原始的优先级依赖树机制,现代实现可以使用 HTTP Extensible Priorities(RFC 9218)中的 Priority 首部等方式表达紧急程度和增量处理偏好。优先级只是调度建议,不能保证服务器一定按照某种顺序发送。

HTTP/2 传统流优先级示意图

4. Server Push

HTTP/2 规范定义了 Server Push。服务器可以在客户端请求 HTML 后,通过 PUSH_PROMISE 预先声明并发送客户端可能需要的资源,例如 CSS 或 JavaScript,从而减少客户端解析 HTML 后再发起请求的等待时间。

客户端可以通过设置禁用推送,也可以使用 RST_STREAM 取消不需要的推送。服务器推送还必须考虑缓存状态、资源是否真的需要以及带宽竞争问题;错误的推送可能浪费带宽,甚至拖慢真正重要的资源。

规范层面仍然可以描述 Server Push,但 Chrome 等主流浏览器已经基本停止支持或默认关闭该功能,现代网站很少把它作为主要性能优化手段。当前更常见的替代方式包括合理的缓存、预加载、103 Early Hints 和资源优先级控制。

HTTP/2 Server Push 示意图

5. HTTP/2 与安全性

HTTP/2 的二进制格式本身不等于加密。规范允许使用明文 HTTP/2,协议标识为 h2c;但主流浏览器通常只在 TLS 上使用 HTTP/2,使用 ALPN 协商的加密协议标识为 h2

因此,现实中浏览器访问的 HTTP/2 网站通常是 HTTPS,但安全性主要来自 TLS,而不是来自 HTTP/2 的二进制分帧。部署 HTTP/2 时还应正确配置证书、TLS 版本、密码套件和 ALPN。

HTTP/2 的 h2 与 h2c 示意图

四、HTTP/3 的背景与新特性

1. HTTP/2 的局限

HTTP/2 解决了 HTTP/1.1 的部分应用层问题,但它通常仍运行在 TCP 之上,因此继承了 TCP 的连接级特性。主要局限包括:

  • TCP 和 TCP+TLS 的连接建立延迟;
  • TCP 的连接级队头阻塞;
  • 大量并发流带来的服务器资源压力。

连接建立延迟

使用 HTTPS 的 HTTP/2 连接通常涉及 TCP 和 TLS 两个阶段:

  1. TCP 三次握手通常按约 1 个 RTT 估算。客户端在收到 SYN+ACK 后可以把数据与最后的 ACK 一起发送,但服务器仍需要等待 TCP 状态建立;
  2. TLS 1.2 完整握手通常还需要约 2 个 RTT,恢复连接时可能更少;
  3. TLS 1.3 完整握手通常还需要约 1 个 RTT,恢复会话时可以发送 0-RTT 早期数据,但早期数据存在重放风险。

因此,不能笼统地说 HTTP/2 一定需要 3~4 个 RTT。实际延迟还受到 DNS、代理、证书验证、连接复用、缓存和网络拥塞等因素影响。

RTT(Round-Trip Time) 表示信号或报文从一端到另一端并返回所经历的往返时延。它不一定等同于“发送数据后立即收到 ACK 的时间”,因为 TCP 可能延迟确认,应用层响应也可能晚于传输层 ACK。

TCP 层的队头阻塞

HTTP/2 的多个流共享一个 TCP 连接。TCP 提供的是有序字节流,当某个 TCP 报文段丢失时,即使后续报文已经到达,TCP 也通常要等待缺失数据重传并恢复顺序后,才会继续向 HTTP/2 交付后续字节。

因此,一个 TCP 丢包可能暂时阻塞同一连接中的多个 HTTP/2 流。这是 HTTP/2 没有彻底解决的 TCP 层队头阻塞。HTTP/1.1 使用多个连接时,可以把影响限制在某一个连接中,但会增加连接、TLS 和拥塞控制开销。

RTO(Retransmission Timeout)是重传超时时间。TCP 会根据连接的 RTT 和波动情况动态计算 RTO;TCP ACK 通常表示接收方希望收到的下一个字节序号,而不是简单表示“下一组数据包的序号”。

HTTP/2 共享 TCP 连接示意图

TCP 已经部署在大量操作系统、网络设备和中间盒中,不能轻易改变其基本的有序字节流语义。但 TCP 仍然可以通过选项和拥塞控制算法持续演进,HTTP/3 则选择在 UDP 之上重新实现一套适合多路复用的可靠传输协议 QUIC。

2. HTTP/3 简介

HTTP/3 是将 HTTP 语义运行在 QUIC 之上的协议。QUIC 使用 UDP 作为底层数据报承载,但在 UDP 之上实现了可靠传输、拥塞控制、流量控制、加密握手和多路复用。

HTTP/3 已经完成标准化,主要规范是 RFC 9114;QUIC 的传输规范是 RFC 9000。HTTP/3 并不是简单地把 HTTP/2 的帧放进 UDP,而是使用 QUIC 的流、帧和 TLS 1.3 机制重新组织传输。

HTTP/3 与 QUIC 关系示意图

QUIC 主要解决的是 TCP 连接级队头阻塞和连接迁移问题,但并不保证所有网络环境下都比 HTTP/2 快。UDP 可能受到网络设备限速、丢包和部署策略影响,最终性能仍取决于具体网络和实现。

3. QUIC 的主要特性

3.1 在 UDP 之上提供可靠传输

UDP 本身不提供可靠性、连接状态、拥塞控制和有序字节流,但 QUIC 在 UDP 之上补充了这些能力。QUIC 流数据可以进行确认、丢包检测和重传,连接还具有流量控制和拥塞控制。

QUIC 并不保证数据在任何故障条件下“一定能够抵达”。如果连接断开、对端不可用或重传次数耗尽,应用程序仍会收到失败结果。

QUIC 的 Packet Number 用于识别数据包和进行丢包检测,流数据的顺序则由每个 Stream 内的偏移量维护。QUIC 丢包恢复时通常重新发送需要恢复的帧,并将它们放入具有新 Packet Number 的数据包中,而不是简单重传完全相同的 UDP 数据包。

3.2 快速握手与 0-RTT

QUIC 将 TLS 1.3 集成到连接建立过程中。新的 QUIC 连接通常需要约 1-RTT 完成握手;如果客户端拥有之前会话的恢复信息,则可能使用 0-RTT 发送早期应用数据。

0-RTT 不是首次连接都能使用,也不代表完整连接已经完成。早期数据发送后,TLS 和 QUIC 握手仍需要继续完成。0-RTT 数据具有重放风险,并且不具备完整的前向保密性,因此只适合幂等、可安全重复执行的请求,不适合直接承载支付、转账等不可重复操作。

TLS 1.3 的 1-RTT 数据通常具有前向保密性;0-RTT 数据使用恢复会话的 PSK 相关密钥,在密钥泄露时可能使攻击者解密之前捕获的 0-RTT 数据。服务器还应采取票据轮换、重放检测和请求限制等措施。

3.3 集成 TLS 1.3

QUIC 强制使用 TLS 1.3 进行握手和密钥协商。TLS 负责身份认证和加密,QUIC 负责传输层的包号、ACK、流量控制、丢包恢复和拥塞控制。两者共同完成安全可靠的传输。

3.4 基于流的多路复用

QUIC 允许同一连接包含多个相互独立的逻辑流。一个流中的数据丢失时,只会阻塞该流中需要按序交付的数据,其他流仍可以继续处理已收到的数据,从而避免 TCP 连接级队头阻塞。

但这并不意味着队头阻塞被“彻底解决”:

  • 单个流内部仍然需要按序交付;
  • 连接级流量控制和拥塞控制仍会影响所有流;
  • HTTP/3 使用 QPACK 压缩首部时,某些动态表依赖也可能产生等待;
  • 服务器和客户端的调度、CPU、内存及带宽仍然是共享资源。

QUIC 多路复用与独立流示意图

3.5 连接迁移

传统 TCP 连接通常由客户端 IP、客户端端口、服务器 IP 和服务器端口组成的四元组识别。网络切换或 NAT 重绑定后,四元组可能发生变化,TCP 通常需要重新建立连接。

QUIC 使用 Connection ID 辅助识别连接。Connection ID 由连接端点发放和管理,长度可变,并不是固定的 64 位。只要满足握手已确认、路径验证通过以及其他迁移条件,客户端在切换网络或地址后可以继续使用同一个 QUIC 连接,而不必重新建立完整连接。

连接迁移并不是只要 Connection ID 不变就一定成功。QUIC 需要对新路径进行验证,服务器也需要遵守对新地址发送数据的限制。QUIC 的密钥上下文可以在迁移后继续使用,但仍可能发生密钥更新和路径相关的拥塞控制调整。

3.6 HTTP/3 的首部压缩

HTTP/3 不使用 HTTP/2 的 HPACK,而是使用为 QUIC 多流传输设计的 QPACK。QPACK 通过静态表、动态表和编码器/解码器流压缩首部,同时允许实现根据压缩效率和阻塞风险进行权衡。

五、HTTP/2 与 HTTP/3 的对比

特性HTTP/1.1HTTP/2HTTP/3
传输格式文本报文二进制帧HTTP/3 帧运行在 QUIC 流上
底层传输TCPTCPUDP + QUIC
首部压缩无通用动态压缩HPACKQPACK
多路复用依赖多个连接或管道化同一 TCP 连接的多个流QUIC 连接的多个独立流
TCP 连接级队头阻塞每个连接分别存在存在由 QUIC 避免
加密可使用 TLS浏览器通常使用 TLSQUIC 强制集成 TLS 1.3
服务器推送无标准推送流规范支持,但浏览器实际使用很少规范支持,但实际使用同样有限
连接迁移通常需要重新连接TCP 本身不支持QUIC 支持路径验证后的迁移

六、总结

  • HTTP/1.1 的主要性能问题包括同一连接上的请求排队、首部重复和连接建立开销;域名分片、雪碧图、资源内联等旧优化需要结合实际场景使用。
  • HTTP/2 保留了 HTTP 的主要语义,但使用二进制分帧、HPACK 和多路复用提高传输效率。它通常可以减少 HTTP 层队头阻塞,但仍受到 TCP 连接级队头阻塞影响。
  • HTTP/2 的 Server Push 仍存在于规范中,但已经不是主流浏览器普遍使用的性能手段。
  • HTTP/3 将 HTTP 运行在 QUIC 之上,使用 QPACK、独立流、TLS 1.3、0-RTT 和连接迁移等能力,主要解决 TCP 连接级队头阻塞和网络切换问题。
  • HTTP/2 和 HTTP/3 都不保证一定更快,最终效果取决于网络、资源、服务器、客户端、缓存和部署方式。

参考资料

457 DOCUMENTS · 10 COLLECTIONS
ARCHIVE SEARCH457 篇文章

SEARCH GUIDE

输入关键词开始搜索

支持搜索文章标题、所属分类和原始文档路径。

按分类浏览

10 COLLECTIONS