超文本传输协议自诞生以来已经发生了巨大的演变,而 HTTP/2 代表着我们在全球网络上传输数据的方式上最重大的飞跃之一。如果你注意到过去几年网页加载速度加快了,那么很有可能是HTTP/2 在幕后发挥作用。
本指南将为您介绍有关HTTP/2 的所有知识–从其核心机制和性能优势到实际部署步骤。无论您是希望优化网络服务器的开发人员,还是仅仅对现代网站的运行方式感到好奇,您都能在这里找到可行的见解。
快速解答:什么是 HTTP/2 及其重要性
HTTP/2 是对超文本传输协议 1.1 版的重大修订,由互联网工程任务组在RFC 7540(2015 年 5 月)中进行了标准化。它的重点是减少延迟,提高网络资源利用率,使网页加载速度明显加快,同时保持与现有 HTTP 语义的完全向后兼容。
2026 年,HTTP/2 的应用几乎无处不在。根据 W3Techs 的数据,超过 1/3 的顶级网站积极使用 HTTP /2,大多数主要 CDN(Cloudflare、AWS CloudFront、Fastly)默认为 HTTPS 流量启用 HTTP/ 2。如果您的网站使用现代网络服务器在 HTTPS 上运行,您很可能已经受益于 HTTP/2,而无需任何额外配置。
该协议引入了几个重要功能,以解决 HTTP 1.1 的性能瓶颈:
- 多路复用:多个数据流同时通过一个 TCP 连接传输
- 头压缩 (HPACK):引入头字段压缩,大幅减少冗余 HTTP 头元数据
- 二进制框架层完全通用的框架层,以高效的二进制信息框架取代基于文本的命令
- 服务器推送:在浏览器明确提出请求之前主动交付资源
- 流优先级:告诉服务器哪些资源最重要的客户端提示
这意味着什么?
- 页面加载速度更快,尤其是在资源繁重的网站上
- 每个原点所需的 TCP 连接更少
- 在高延迟移动网络上性能更佳
- 全面提高网络利用率
从 HTTP/0.9 到 HTTP/2:简史
自1991 年蒂姆-伯纳斯-李推出 HTTP/0.9作为获取 HTML 文档的简单机制以来,HTTP 协议已经走过了漫长的历程。HTTP/1.0 于 1996 年推出,增加了标头和状态代码,HTTP/1 .1 在 RFC 2068(1997 年)中被标准化,随后在 RFC 2616(1999 年)中得到完善。近二十年来,HTTP/1.1一直是整个网络客户端-服务器通信的支柱。
但网络发生了翻天覆地的变化。现代网页从简单的文档变成了加载数十个 JavaScript 包、CSS 文件、图像和 API 调用的复杂应用程序。即使有宽带连接和强大的硬件,HTTP/1.1 的架构也会造成瓶颈:
- 线路阻塞:每个 TCP 连接一次只能处理一个请求,导致资源排队,造成不必要的网络流量
- 连接开销:桌面网络浏览器和移动网络浏览器通常会为每个起源打开 6-8 个并行 TCP 连接,以解决这一限制问题
- 冗余标头:每个 HTTP 请求都重复发送相同的冗长标头(cookie、用户代理、接受标头)。
谷歌意识到了这些问题,并于2009 年启动了 SPDY 项目。SPDY于 2010 年左右首次在 Chrome 浏览器中实施,并引入了多项创新:
- 二进制框架取代基于文本的协议
- 通过单个连接复用多个请求
- 压缩报头以减少开销
- 确定关键资源流的优先次序
IETF HTTP 工作组看到了 SPDY 的潜力,并于 2012 年将其作为 HTTP/2 的起点。经过 IETF HTTP 工作组的大量工作,RFC 7540(HTTP/2)和 RFC 7541(HPACK)于 2015 年 5 月发布。
浏览器的采用速度很快:
- 从 Chrome 51(2016 年 5 月)开始,Chrome 不再使用 SPDY,转而使用 HTTP/2
- 火狐浏览器在第 36 版(2015 年 2 月)中添加了 HTTP/2 支持
- Safari 浏览器后续版本 9(2015 年 9 月)
- Microsoft Edge 从发布之初就支持 HTTP/2
- 甚至 Internet Explorer 11 也在 Windows 8.1 及更高版本上获得了 HTTP/2 支持
设计目标和与 HTTP/1.1 的主要区别
HTTP/2 与 HTTP/1.1 语义保持完全兼容。 GET和POST等方法的工作原理相同。状态代码保持不变。URI 和 HTTP 头域遵循相同的规则。 变化的是这些数据如何在线路上移动,即决定实际负载速度的传输层机制。
协议的设计目标非常明确:
| 目标 | HTTP/2 如何实现 |
|---|---|
| 减少延迟 | 多路复用消除了 HTTP 级线路头部阻塞 |
| 更好地使用连接 | 单个 TCP 连接可处理向原点发出的所有请求 |
| 切割头顶 | HPACK 压缩可缩小先前传输的标头值 |
| 提高移动性能 | 更少的连接和更小的报头有利于高延迟网络 |
这种设计的优点在于应用层的向后兼容性。您现有的网络应用程序代码–路径、处理程序、响应逻辑–无需更改。只有客户端和服务器堆栈必须支持 HTTP/2 才能获益。
这与 HTTP/1.1 的变通方法形成鲜明对比,后者需要开发人员手动实施:
- 域分片:将资产分散到多个域,以打开更多连接
- 资产串联:捆绑 CSS 和 JavaScript 文件以减少请求次数
- 图像精灵将多个图像合并为单个文件
- 内嵌:直接在 HTML 中嵌入 CSS 和 JavaScript
HTTP/2 的核心机制取代了这些黑客手段:
- 二进制成帧层:分割成帧的报文作为二进制协议单元有效传输数据
- 多路复用流:通过同一连接进行多个并发交换
- HPACK 标头压缩动态表跟踪报头,消除冗余
- 服务器推送:服务器主动发送客户端需要的资源
- 流优先级:客户端通过数据流相关性权重显示哪些资源最重要
二进制成帧、流、信息和多路复用
HTTP/2 的核心是二进制框架层,与 HTTP/1.1 基于文本的格式截然不同。每个 HTTP 报文都被分解成二进制帧,帧布局保持一致:9 字节的帧头包含长度、类型、标志和流标识符,后面是可选的有效载荷数据。
理解层次结构需要掌握三个概念:
数据流是单个连接中独立的双向通道。每个数据流都有一个唯一的 31 位标识符。客户端使用奇数 ID(1、3、5……)启动数据流,而服务器使用偶数 ID(2、4、6……)启动推送等数据流。意外的流标识符会引发错误。最大并发流设置可控制同时激活的并发流数量。
信息代表完整的 HTTP 请求或响应。一个完整的标题块由一个或多个帧组成,而响应可能包括多个主体数据帧。当接收方遇到报头块碎片时,会将它们重新组合,以重建完整的报文。
帧是线路上最小的单位。常见的帧和错误类型包括
- 数据帧:携带请求/响应正文内容
- HEADERS 框架:包含 HTTP 头字段,可能被分割成多个框架,称为头块片段
- 设置:用于配置的连接控制信息
- WINDOW_UPDATE:流量控制窗口调整
- PUSH_PROMISE:宣布服务器推送
- RST_STREAM:使用错误代码终止数据流
- GOAWAY:启动优美的连接关闭
多路复用是一种神奇的技术。因为来自多个同时打开的数据流的帧可以在单个 TCP 连接上交错–任何一个端点都可以根据需要交错帧,所以无需等待。接收器按流标识符重新组装帧。
考虑加载一个典型的网页,该网页需要
- index.html (10 KB)
- styles.css (25 KB)
- app.js (100 KB)
- 徽标.png (15 KB)
- 英雄图像.jpg (200 KB)
使用 HTTP/1.1 时,浏览器会打开多个连接来并行获取这些资源,但仍会受到限制。有了 HTTP/2,所有五种资源都以多个数据流的形式在一个连接上并发传输。来自不同数据流的数据帧交错排列,客户端和服务器都能高效地管理整个连接。
这样就不需要多个 TCP 连接,减少了连接流量控制窗口的开销,显著提高了网络性能。
使用 HPACK 压缩报头
RFC 7541(2015 年 5 月与 HTTP/2 同时发布)中定义的 HPACK 提供了专为 HTTP/2 设计的报头压缩。这很重要,因为 HTTP/1.1 标头冗长且完全未压缩,会对每个请求造成不必要的网络流量。
请看一个典型的 HTTP 请求头:
Host: example.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)...
Accept: text/html,application/xhtml+xml,application/xml;q=0.9...
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Cookie: session=abc123def456; tracking=xyz789...
每个请求的这些标头通常超过 700-800 字节。如果使用 cookie,则可能会膨胀到几千字节。再乘以每个页面的几十个请求,就会浪费大量带宽–在移动网络上尤其如此。
HPACK 通过三种机制压缩报头:
- 静态表:61 个预定义的通用报头字段/值对(如 :method: GET 或 :status: 200),无需传输
- 动态表:客户机和服务器共同建立的特定连接表,存储先前传输的标头值,以便重复使用
- 哈夫曼编码:使用预定义的哈夫曼表对字符串值进行编码,缩小文本表示范围
这样做的效果非常明显。在第一个请求在动态表中建立了通用标头后,随后的请求可能只传输索引引用。从开始的几千字节缩减到几十字节。
HPACK 专为避免 CRIME 和 BREACH 等安全漏洞而设计,这些漏洞影响了 SPDY 的 DEFLATE 等早期压缩方案。通过使用静态哈夫曼代码和谨慎的表管理,HPACK 可以防止攻击者利用压缩比分析从攻击者/受害者混合数据中提取机密。
值得注意的是,HPACK 只对 HTTP 头进行压缩。响应体仍在 HTTP 层使用 gzip 或 Brotli 等标准内容编码机制,与报头压缩完全分离。
服务器推送和数据流优先级
HTTP/2 引入了两项优化功能,旨在取代 HTTP/1.1 的变通方法:用于主动资源交付的服务器推送和用于智能资源排序的流优先级。
服务器推送
服务器推送允许网络服务器在客户端明确提出请求之前向其发送资源。该机制通过 PUSH_PROMISE 框架运行:
- 客户请求 /index.html
- 服务器响应 HTML,但同时发送 PUSH_PROMISE 框架,宣布将推送 /styles.css 和 /app.js
- 服务器将这些资源发送到新的服务器启动的数据流上(根据低值数据流标识符分配规则,数据流标识符使用偶数)。
- 浏览器在解析 HTML 发现需要资源之前接收资源
这样就省去了往返次数。而不是
- 请求 HTML → 接收 HTML
- 解析 HTML,发现所需 CSS → 申请 CSS
- 解析 CSS,发现所需字体 → 申请字体
服务器推送将第 2-3 步合并为第 1 步。
然而,实践证明服务器推送存在问题:
- 浏览器可能已经缓存了资源,导致推送浪费
- 配置不当的服务器推送过猛,浪费带宽
- 缓存摘要机制从未得到广泛采用
- 许多 CDN 和浏览器现在都限制或默认禁用推送功能
客户端可以通过在连接前言中设置 SETTINGS_ENABLE_PUSH = 0 来完全禁用推送。当客户端连接前言立即禁用推送时,服务器连接前言包括确认和遵从。
确定溪流优先次序
流优先级让客户端发出资源重要性信号,帮助服务器有效分配带宽。该机制使用
- 权重:1-256 之间的数值表示相对重要性
- 依赖关系流可以依赖于其他流,通过流依赖声明形成一棵依赖树
实例
- HTML 数据流(权重 256,无依赖性)–最高优先级
- CSS 流(权重 200,取决于 HTML)–高优先级
- 折叠上方图像(权重 100,取决于 CSS)
- 分析 JavaScript(权重 16,取决于 HTML)–低优先级
这样就能确保关键的渲染路径资源优先到达,即使总传输时间仍然相似,也能提高感知加载速度。
重要注意事项
- 优先顺序是咨询性的,而非强制性的
- 服务器的实现方式大相径庭
- 中介(代理、CDN)可能会重新排序帧
- 调整需要使用真实流量进行测试,而不是假设
广告并发流限制会影响同时有多少个流具有活动优先级。
流量控制、错误处理和安全考虑因素
HTTP/2 在 TCP 上实现了自己的流量控制和错误处理,解决了应用层智能优于传输层默认设置的问题。
流量控制
流量控制可防止快速发送方压倒慢速接收方。HTTP/2 通过 WINDOW_UPDATE 帧使用基于信用的系统:
- 每个数据流都有自己的接收器流量控制窗口
- 该连接还有一个连接流量控制窗口
- 默认窗口大小:65,535 字节(64 KB)
- 发送方不能发送超过接收方可用窗口的数据帧
- 接收器发送 WINDOW_UPDATE 帧以授予更多积分
主要特点
- 逐跳流量控制(适用于每对发送方/接收方之间)
- 不能禁用
- 只有数据帧才计入窗口,其他必填帧数据不计入窗口
- 流控制和连接流控制均独立运行
这可以防止单个快速流垄断连接资源,在代理或 CDN 位于客户端和源端之间时尤为重要。
错误处理
HTTP/2 提供细粒度的错误信号:
- 流级错误:RST_STREAM 会立即终止一个数据流,而不影响其他数据流,并带有 PROTOCOL_ERROR 或 FLOW_CONTROL_ERROR 等错误代码
- 连接级错误:GOAWAY 会优雅地关闭连接,允许完成飞行中的请求,同时防止出现新的请求
协议定义的错误代码登记表包括
- PROTOCOL_ERROR (0x1):违反一般协议
- FLOW_CONTROL_ERROR (0x3):违反流量控制规则
- FRAME_SIZE_ERROR (0x6):帧超出 SETTINGS_MAX_FRAME_SIZE
- INADEQUATE_SECURITY (0xc):传输层安全配置不足
安全考虑因素
虽然 RFC 7540 在技术上并不要求加密,但所有主要网络浏览器都要求 HTTP/2 采用传输层安全(TLS)。这使得 TLS 1.2+ 成为事实上的基准:
- 连接开始时进行 TLS 握手,包括 ALPN(应用层协议协商)
- ALPN 扩展协商 HTTP/2 的 “h2 “标识符
- 服务器必须避免被规范列入黑名单的弱密码套件
- 使用 RC4 或其他过时算法的密码套件会触发 INADEQUATE_SECURITY 错误
隐私方面的考虑包括
- 设置和优先级模式可对客户端进行指纹识别
- 每个来源地的单一连接可将所有用户活动与该来源地相关联
- 二进制协议可掩盖流量,但无法瞒过网络观察者
TCP 线头封堵
HTTP/2 通过多路复用解决了 HTTP 级的线头阻塞,但 TCP 级的阻塞依然存在。当 TCP 数据包丢失时,该连接上的所有数据流都会停滞,直到重新传输完成,即使数据成功到达的数据流也不例外。
这种限制促使 HTTP/3 在 QUIC(基于 UDP)上运行,以提供真正的流独立性。影响一个数据流的数据包丢失不会阻塞其他数据流。
在实践中部署和使用 HTTP/2
在 2026 年,启用 HTTP/2 非常简单。大多数现代网络服务器和 CDN 开箱即支持 HTTP/2,主要是通过 HTTPS。HTTP 升级机制以透明方式处理协商。
客户端要求
用户不需要做任何特别的事情:
- 所有现代桌面网络浏览器(Chrome、Firefox、Safari、Edge)默认都支持 HTTP/2
- 移动网络浏览器(Android 的 Chrome 浏览器和 iOS 的 Safari)包括全面支持
- 使用最新版本的浏览器确保兼容性
- HTTP/2 可用时自动协商
服务器端配置
Apache HTTP 服务器 (2.4.17+):
- 启用 mod_http2 模块(而不是较旧的 mod_spdy 模块)
- 在 TLS 虚拟主机中添加协议 h2 http/1.1
- 确保 OpenSSL 版本支持 ALPN
Nginx (1.9.5+):
server {
listen 443 ssl http2;
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
# ... rest of configuration
}
IIS(Windows Server 2016+):
- 使用 TLS 1.2+ 的 HTTPS 默认已启用 HTTP/2
- 无需额外配置
CDN 提供商:
- Cloudflare:所有计划默认启用 HTTP/2
- AWS CloudFront:默认已为 HTTPS 分发启用
- Fastly: 支持并默认启用
验证和故障排除
使用此清单确认 HTTP/2 是否正常工作:
- 浏览器 DevTools:打开 “网络 “选项卡,启用 “协议 “栏,查找 “h2
- 命令行:curl –http2 -I https://example.com 在响应中显示 HTTP/2
- 在线工具:HTTP/2 测试服务验证配置
- 检查中介:CDN 或反向代理必须支持 HTTP/2,而不仅仅是源服务器
阻碍 HTTP/2 的常见问题
- OpenSSL 版本太旧,无法支持 ALPN
- 仅 TLS 1.0/1.1 配置
- 触发回退的弱密码套件
- 配置错误的代理剥夺了 HTTP/2 支持
HTTP/2 及其他
HTTP/2 仍是现代网络通信的主流协议,即使 HTTP/3(RFC 9114,2022 年发布)已开始部署。HTTP/3 通过在 QUIC 上运行解决了 TCP 线头阻塞问题,但 HTTP/2 的单一 TCP 连接模型仍能有效地服务于大部分网络流量。
对于大多数网站而言,HTTP/2 只需极少的配置工作即可大幅提高网站性能。现在就开始通过 HTTP/2 交换框架,您的用户–无论是台式机用户还是移动用户–都将体验到更快、更高效的页面加载。
主要收获
- HTTP/2 通过多路复用彻底改变了网络性能,允许通过单个连接进行多个并发交换
- HPACK 报头压缩消除了多余的报头传输,移动用户尤其受益
- 服务器推送和数据流优先级优化了资源交付,但实施情况各不相同
- 流量控制可防止多个数据流之间出现资源短缺现象
- 在现代服务器上部署非常简单,主要需要进行 HTTPS 配置
- 所有主流浏览器都支持 HTTP/2,终端用户可无缝采用
下一步工作
如果您尚未在网络服务器上验证 HTTP/2,现在正是时候。打开浏览器的开发工具,加载您的网站,然后检查协议栏。如果你看到的是 “http/1.1 “而不是 “h2″,请检查你的服务器配置–你可能会在性能提升上留下巨大的遗憾。
对于已经运行 HTTP/2 的用户,请考虑监控服务器的 HTTP/2 连接指标。了解多个并发流在实际流量下的表现,有助于在用户发现问题之前找到优化机会。