简介
HTTP/2(RFC 7540,2015 年发布)是自 1999 年 HTTP/1.1 以来的第一次重大升级,目标是在不改变应用语义的前提下,改善延迟、并发和网络效率。浏览器端基本只在 TLS 上启用(h2),明文 h2c 仅用于内部服务间通信。
- h2:HTTP/2 over TLS(最常见,浏览器只支持这一种)
- h2c:HTTP/2 over TCP(无加密)
设计背景
移动端和富媒体时代请求量激增,HTTP/1.1 的队头阻塞、多个 TCP 连接并行带来的慢启动 / 拥塞竞争成为瓶颈。
谷歌的 SPDY 原型验证了「单连接、多路复用、压缩头部」的思路;IETF 在 SPDY 3.1 基础上标准化为 HTTP/2。
核心特性
| 特性 | 作用 |
|---|---|
| 二进制分帧(Binary Framing) | 把 HTTP 报文拆成小型 Frame,机器易解析、可并行 |
| 多路复用(Multiplexing) | 多个请求 / 响应共享一个 TCP 连接,互不阻塞 |
| 流与优先级(Stream & Priority) | 每个请求是双向 Stream,可指定权重与依赖 |
| 头部压缩(HPACK) | 静态 Huffman + 动态表,大幅减少重复 Header 字节 |
| 服务器推送(Server Push) | Chrome 106(2022-09)已移除,由 103 Early Hints 取代 |
| 流量控制 | 端到端窗口,避免单个大文件占满带宽 |
多路复用解决的是应用层队头阻塞 —— TCP 层的队头阻塞依然存在(任意一个包丢失,连接上所有 stream 全停),这正是 HTTP/3 改走 QUIC over UDP 要解决的问题。
NGINX 配置
启用 HTTP/2 需要 HTTPS,本地证书参考 在本地环境使用 HTTPS | ZYF.IM。
# /etc/nginx/conf.d/default.conf
server {
listen 443 ssl;
http2 on; # NGINX 1.25.1+ 的新语法
server_name localhost;
ssl_certificate /etc/ssl/certs/localhost.pem;
ssl_certificate_key /etc/ssl/certs/localhost-key.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5; # demo 用,生产请见下文
ssl_prefer_server_ciphers on;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
}
docker container restart nginx-ssl
几个常被问到的细节
http2 on;的版本要求。NGINX 1.25.1(2023-05)才引入独立的http2指令,更早的版本要写listen 443 ssl http2;。老语法仍可用,但已被官方建议替换。- ALPN 协商。HTTP/2 over TLS 必须靠 ALPN 在 TLS 握手时协商出
h2。OpenSSL 1.0.2+ 默认支持,NGINX 启用 TLS 即自动具备,不需要额外指令。 - cipher 列表别复制 demo。
HIGH:!aNULL:!MD5是 NGINX 默认列表,还包含一些过时套件。生产环境请用 Mozilla SSL Configuration Generator 生成 intermediate 或 modern 配置,自动剔除 RC4、3DES、CBC mode 等弱套件。 - Server Push 已死,用 103 Early Hints。Chrome 106 正式移除 push 支持。替代方案是服务器在主响应前发一个
103 Early Hints响应,携带Link: </app.css>; rel=preload,浏览器立即开始拉取。NGINX 1.13.9+ 通过ngx_http_v2_module的http2_push_preload已不推荐,HTTP 层的 Early Hints 需要应用配合。 - HPACK → QPACK。HTTP/2 的 HPACK 因动态表有顺序依赖,会被 TCP 队头阻塞拖累;HTTP/3 改用 QPACK 解耦编解码顺序。这是 HTTP/3 性能优势的关键设计之一。
测试
浏览器
访问 https://localhost:8443/,Chrome DevTools Network 面板勾选 Protocol 列,看到 h2 即生效。
或装 HTTP Indicator 扩展:HTTP/1.1 灰、HTTP/2 蓝、HTTP/3 绿。
curl
# -I (--head) 只返回响应头
curl -I https://localhost:8443/
HTTP/2 200
server: nginx/1.29.0
date: Fri, 27 Jun 2025 01:56:55 GMT
content-type: text/html
content-length: 615
nghttp / h2load
nghttp2 工具包提供更底层的视图,能打出 ALPN 协商结果、HPACK 表、stream 详情:
brew install nghttp2
nghttp -nv https://localhost:8443/ # 单请求 + 详细协议输出
h2load -n 1000 -c 10 https://localhost:8443/ # 1000 请求 / 10 连接的压测
h2load 还能直接对比 h1 / h2 / h3 的吞吐 (--h1、--alpn-list=h3,h2),调参时比 ab 更贴近真实场景。
HTTP/3
References
– EOF –