HTTP/2 是 HTTP/1.1 的下一代协议,核心目标是提升性能(减少延迟、提高吞吐量),它的升级可以基于两种底层传输层场景:
- TCP 明文升级:从 HTTP/1.1(明文 TCP)升级到 HTTP/2(明文 TCP)
- TLS 加密升级 :从 HTTPS(HTTP/1.1 + TLS)升级到 HTTP/2(HTTPS + TLS,也叫
h2)
HTTP/2 定义了两种部署方式:
- h2c :基于明文 TCP 的 HTTP/2(
c代表cleartext) - h2 :基于 TLS 1.2+ 的加密 HTTP/2(主流部署方式,浏览器仅支持
h2)
先明确 HTTP/2 的核心特性(也是升级的价值):
| 特性 | HTTP/1.1 | HTTP/2 |
|---|---|---|
| 多路复用 | 单连接单请求(需开启 pipelining 且效果有限) | 单连接多请求并行,互不阻塞 |
| 头部压缩 | 明文传输,重复头部无压缩 | HPACK 算法压缩头部,减少带宽 |
| 二进制帧 | 文本格式(易解析但冗余) | 二进制格式(高效、紧凑) |
| 服务器推送 | 无 | 主动推送资源到客户端,提前缓存 |
| 流优先级 | 无 | 客户端可指定请求优先级,优化资源加载 |
其中HTTP/2的服务器推送,是服务器主动向客户端发送数据,该行为的前提是客户端先发起了一个请求,且推送的是和这个请求相关的资源。
比如客户端请求
index.html,服务器分析到这个页面需要style.css和app.js,就会在返回index.html的同时,主动把style.css和app.js推送给客户端,不需要客户端再发这两个资源的请求。它的 "单向" 是指:只有服务器能推给客户端,客户端不能推给服务器 ;且推送是请求触发的被动预推,不是服务器凭空主动发数据。
可以理解为:
- HTTP/1.1 是 "点菜→上菜",点一个菜上一个菜;
- HTTP/2 推送是 "点菜→上菜 + 送配菜",点一个主菜,店家主动把搭配的配菜一起送过来,不用再点配菜。
一、 从 HTTP/1.1(明文 TCP)升级到 HTTP/2(h2c)
这种方式基于明文 TCP 连接 ,不需要 TLS 加密,主要用于服务器内部通信、非浏览器客户端(如 API 调用),因为主流浏览器不支持 h2c(出于安全考虑)。
升级原理
HTTP/1.1 定义了 Upgrade 机制,允许客户端和服务器在已建立的 TCP 连接上切换协议。h2c 升级就是基于这个机制实现的。
完整升级流程(客户端主动发起)
-
建立 TCP 连接客户端向服务器的 HTTP 端口(默认 80)发起 TCP 三次握手,建立明文 TCP 连接。
-
发送 HTTP/1.1 升级请求客户端发送一个特殊的 HTTP/1.1 请求,携带以下关键头部:
GET / HTTP/1.1 Host: example.com Upgrade: h2c # 声明要升级到的协议是 h2c Connection: Upgrade # 告诉服务器这是一个升级请求 HTTP2-Settings: AAMAAABkAAQAAP__ # HTTP/2 配置参数的 Base64 编码HTTP2-Settings:携带客户端的 HTTP/2 初始配置(如流窗口大小、最大并发流数),是 Base64 编码的二进制帧,服务器解析后确认是否支持。
-
服务器响应升级 服务器如果支持 h2c,会返回 101 Switching Protocols 响应:
HTTP/1.1 101 Switching Protocols Upgrade: h2c Connection: Upgrade响应后,TCP 连接的协议从 HTTP/1.1 切换为 HTTP/2,后续通信全部使用 HTTP/2 的二进制帧格式。
-
HTTP/2 通信阶段 客户端和服务器基于同一个 TCP 连接,通过流(Stream) 并行传输多个请求 / 响应,实现多路复用。
注意事项
- 浏览器不支持 h2c 升级 :Chrome、Firefox 等浏览器明确禁用了 h2c,仅支持
h2(TLS 加密的 HTTP/2)。 - 降级机制:如果服务器不支持 h2c,会返回常规的 HTTP/1.1 响应(如 200 OK),连接继续使用 HTTP/1.1。
- 不支持升级的场景:如果客户端发送的是 POST 请求(带请求体),无法使用
Upgrade机制,必须使用 HTTP/2 的预先生成连接(直接用 HTTP/2 协议握手)。
二、 从 HTTPS(HTTP/1.1 + TLS)升级到 HTTP/2(h2)
这是主流的 HTTP/2 部署方式 ,所有浏览器都支持。h2 是基于 TLS 加密的 HTTP/2,升级的核心是在 TLS 握手阶段协商使用 HTTP/2 协议 ,而不是依赖 HTTP 的 Upgrade 机制。
核心概念:ALPN 协议
ALPN(Application-Layer Protocol Negotiation,应用层协议协商)是 TLS 1.2 及以上版本支持的扩展,它允许客户端和服务器在 TLS 握手时直接协商应用层协议(HTTP/1.1 或 HTTP/2),避免了额外的 HTTP 升级请求,提升了效率。
完整升级流程(TLS 握手协商)
-
建立 TCP 连接客户端向服务器的 HTTPS 端口(默认 443)发起 TCP 三次握手,建立 TCP 连接。
-
TLS 握手 + ALPN 协商这是升级的关键步骤,TLS 握手和协议协商同时进行:
- 客户端 Hello 消息 :客户端发送
ClientHello消息,携带支持的 TLS 版本、加密套件,以及 ALPN 扩展列表 (如[h2, http/1.1]),表示客户端优先支持 HTTP/2,其次是 HTTP/1.1。 - 服务器 Hello 消息 :服务器收到
ClientHello后,选择支持的协议(如果服务器支持 h2,会选择h2),并在ServerHello消息中返回 ALPN 协商结果。 - 完成 TLS 握手:客户端和服务器交换证书、密钥,完成 TLS 1.2+ 握手,建立加密通道。
- 客户端 Hello 消息 :客户端发送
-
直接使用 HTTP/2 通信 TLS 握手完成后,加密通道内的应用层协议直接是 HTTP/2 ,无需再发送 HTTP
Upgrade请求。后续所有请求 / 响应都通过 HTTP/2 的二进制帧传输,实现多路复用、头部压缩等特性。
关键优势(对比 h2c 升级)
- 安全性:基于 TLS 加密,防止数据窃听和篡改。
- 效率更高:通过 ALPN 在 TLS 握手时协商协议,省去了 HTTP/1.1 升级请求的往返时间(RTT)。
- 浏览器支持 :所有现代浏览器(Chrome、Firefox、Safari)均支持
h2。
与 HTTP/1.1 HTTPS 的区别
| 对比项 | HTTP/1.1 + TLS | HTTP/2(h2)+ TLS |
|---|---|---|
| 协议协商 | 无 ALPN(直接用 HTTP/1.1) | 用 ALPN 协商为 h2 |
| 连接复用 | 单连接单请求(需开启 keep-alive) | 单连接多请求并行 |
| 头部传输 | 明文重复传输 | HPACK 压缩传输 |
| 性能 | 受队头阻塞影响 | 无队头阻塞,性能大幅提升 |
三、 升级 HTTP/2 的关键配置与注意事项
1. 服务器端配置要求
-
TLS 版本 :部署
h2必须使用 TLS 1.2 或更高版本,TLS 1.1 及以下不支持 ALPN。 -
禁用不安全加密套件:部分旧加密套件(如 RC4)不支持 HTTP/2,需在服务器配置中禁用。
-
示例配置(Nginx) :
server { listen 443 ssl http2; # 开启 HTTPS + HTTP/2 server_name example.com; ssl_certificate cert.pem; ssl_certificate_key key.pem; ssl_protocols TLSv1.2 TLSv1.3; # 仅支持 TLS 1.2+ ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256; # 其他配置... }关键指令:
http2表示在该端口启用 HTTP/2。
2. 常见问题与解决方案
- 队头阻塞问题 :HTTP/1.1 存在队头阻塞(一个请求阻塞后续请求),HTTP/2 解决了应用层的队头阻塞,但TCP 层的队头阻塞仍然存在(如丢包会导致整个连接阻塞)。HTTP/3 基于 QUIC 协议解决了这个问题。
- 兼容性问题:旧客户端(如 IE 浏览器)不支持 HTTP/2,服务器需配置降级机制,自动回退到 HTTP/1.1。
- 头部压缩风险 :HPACK 压缩可能存在 HPACK 爆破攻击,服务器需限制头部大小和压缩比。
四、 两种升级方式的对比总结
| 特性 | 明文 TCP 升级(h2c) | TLS 加密升级(h2) |
|---|---|---|
| 传输层 | 明文 TCP | 加密 TLS 1.2+ |
| 协议协商 | HTTP Upgrade 机制 | TLS ALPN 扩展 |
| 浏览器支持 | 不支持 | 完全支持 |
| 安全性 | 低(明文传输) | 高(加密传输) |
| 适用场景 | 服务器内部通信、API 服务 | 公网 Web 服务、浏览器访问 |
| 效率 | 需要 1 次额外 HTTP 往返 | 无额外往返,效率更高 |