公告

👇微信扫码添加好友👇

图片
Skip to content

HTTP/2 协议详解

HTTP/2 是 HTTP 协议的重大升级,通过多路复用、头部压缩、服务器推送等特性,显著提升了 Web 性能。

一、HTTP/1.1 的性能瓶颈

1.1 队头阻塞(Head-of-Line Blocking)

客户端                    服务器
  |---- 请求1 ----->|      |
  |                 |---- 响应1 ----->|  ← 必须等待响应1完成
  |---- 请求2 ----->|                 |
  |                 |---- 响应2 ----->|  ← 请求2必须排队

HTTP/1.1 虽然支持持久连接(Keep-Alive),但同一连接上的请求必须串行处理。

1.2 连接数限制

浏览器对同一域名的并发连接数有限制(通常 6-8 个),导致资源加载受限。

1.3 头部冗余

每次请求都会携带大量重复的头部信息(Cookie、User-Agent 等),造成带宽浪费。

1.4 资源合并优化的弊端

为减少请求数,开发者将多个小文件合并成大文件、使用雪碧图等,但这种方式:

  • 增加了缓存失效的粒度
  • 增加了代码复杂度
  • 无法充分利用并行加载

二、HTTP/2 的核心特性

2.1 特性概览

特性说明
二进制分帧将数据分为更小的帧进行传输
多路复用同一连接上并行处理多个请求
头部压缩使用 HPACK 算法压缩头部
服务器推送服务器主动推送资源
流量控制基于窗口的流量控制机制
请求优先级可以设置请求的优先级

2.2 与 HTTP/1.1 的对比

HTTP/1.1:
客户端 -> [请求1] -> [等待] -> [请求2] -> [等待] -> [请求3]
         ──────────────────────────────────────────────────> 时间

HTTP/2:
客户端 -> [帧1][帧2][帧3][帧1][帧2][帧3][帧1][帧2][帧3]
         ──────────────────────────────────────────────────> 时间
         ↑ 三个请求的帧交错传输,无需等待

三、二进制帧格式详解

3.1 帧结构

+-----------------------------------------------+
|                 Length (24)                    |
+---------------+---------------+---------------+
|   Type (8)    |   Flags (8)   |
+-+-------------+---------------+---------------+
|R|                 Stream Identifier (31)       |
+=+=============================================+
|                   Frame Payload (0...)        |
+-----------------------------------------------+
字段长度说明
Length24 位帧负载长度(最大 16MB)
Type8 位帧类型
Flags8 位标志位
R1 位保留位
Stream Identifier31 位流标识符

3.2 帧类型

类型说明
DATA0x0传输数据
HEADERS0x1头部帧
PRIORITY0x2优先级设置
RST_STREAM0x3终止流
SETTINGS0x4设置参数
PUSH_PROMISE0x5推送承诺
PING0x6心跳检测
GOAWAY0x7关闭连接
WINDOW_UPDATE0x8流量控制
CONTINUATION0x9头部延续

3.3 流(Stream)、消息(Message)、帧(Frame)的关系

Stream 1 (请求/响应对)
├── HEADERS 帧 (请求头)
├── DATA 帧 (请求体)
├── HEADERS 帧 (响应头)
└── DATA 帧 (响应体)

Stream 2 (另一个请求/响应对)
├── HEADERS 帧
└── DATA 帧

四、多路复用工作原理

4.1 连接与流

一个 TCP 连接
└── 多个 Stream (流)
    └── 多个 Message (消息)
        └── 多个 Frame (帧)

4.2 并行传输

客户端                               服务器
  |                                    |
  |-- HEADERS (Stream 1) ------------->|
  |-- HEADERS (Stream 3) ------------->|  ← 无需等待 Stream 1
  |-- DATA (Stream 1) ---------------->|
  |-- HEADERS (Stream 5) ------------->|  ← 无需等待
  |<---------- HEADERS (Stream 1) -----|
  |-- DATA (Stream 3) ---------------->|
  |<---------- DATA (Stream 1) --------|
  |<---------- HEADERS (Stream 3) -----|

4.3 解决队头阻塞

  • 应用层:多个请求可以同时传输,互不阻塞
  • 传输层:仍使用 TCP,TCP 层的队头阻塞仍存在

TCP 层队头阻塞

HTTP/2 解决了 HTTP 层的队头阻塞,但 TCP 层的队头阻塞仍然存在。当一个 TCP 包丢失时,所有流都会被阻塞。HTTP/3 使用 QUIC 协议解决了这个问题。

五、HPACK 头部压缩算法

5.1 为什么需要头部压缩

HTTP/1.1 的头部以纯文本传输,存在大量冗余:

GET /index.html HTTP/1.1
Host: example.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)
Accept: text/html,application/xhtml+xml
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8
Accept-Encoding: gzip, deflate, br
Cookie: session=abc123; theme=dark
... (每次请求都重复)

5.2 HPACK 算法原理

HPACK 使用三种方式压缩头部:

1. 静态表(Static Table)

预定义了 61 个常见的头部键值对:

索引头部名称头部值
1:authority
2:methodGET
3:methodPOST
4:path/
.........

2. 动态表(Dynamic Table)

在连接生命周期内动态添加的头部键值对:

首次传输:
  Content-Type: application/json  →  编码为字节序列

后续传输:
  Content-Type: application/json  →  引用动态表索引 (更短)

3. 霍夫曼编码(Huffman Coding)

对头部值进行霍夫曼编码,进一步压缩体积。

5.3 压缩效果

场景压缩前压缩后压缩率
首次请求~800B~200B75%
后续请求~800B~50B94%

六、服务器推送(Server Push)

6.1 工作原理

客户端                     服务器
  |                          |
  |-- GET /index.html ------>|
  |                          |  ← 服务器知道需要 style.css
  |<-- PUSH_PROMISE ---------|  ← 预告要推送 style.css
  |<-- HEADERS (index.html) -|
  |<-- DATA (index.html) ----|
  |<-- HEADERS (style.css) --|  ← 推送的资源
  |<-- DATA (style.css) -----|

6.2 服务器推送配置

Nginx 配置:

nginx
location /index.html {
    http2_push /style.css;
    http2_push /app.js;
}

Node.js (Express):

javascript
app.get('/index.html', (req, res) => {
    const stream = res.push('/style.css', {
        'content-type': 'text/css'
    });
    stream.end(cssContent);
    res.end(htmlContent);
});

6.3 推送的限制

服务器推送的注意事项

  • 推送的资源必须是同源的
  • 客户端可以拒绝推送(发送 RST_STREAM)
  • 不能推送 HTML 页面
  • 过度推送会浪费带宽
  • 实际使用中效果不如预期,Chrome 已计划移除支持

七、HTTP/2 与 HTTPS 的关系

7.1 浏览器要求

浏览器HTTP/2 要求
Chrome必须 HTTPS
Firefox必须 HTTPS
Safari必须 HTTPS
Edge必须 HTTPS

虽然 HTTP/2 规范不强制要求 TLS,但所有主流浏览器都要求 HTTP/2 必须使用 HTTPS。

7.2 TLS 版本要求

  • HTTP/2 通常使用 TLS 1.2+
  • TLS 1.3 提供更快的握手(1-RTT,甚至 0-RTT)

7.3 ALPN 协商

客户端                               服务器
  |                                    |
  |-- ClientHello -------------------->|  ← 包含 h2 协议标识
  |<-- ServerHello --------------------|  ← 选择 h2 协议
  |                                    |
  |       使用 HTTP/2 通信              |

八、浏览器与服务器支持情况

8.1 浏览器支持

浏览器支持版本市场份额
Chrome41+~65%
Firefox36+~15%
Safari9+~10%
Edge12+~5%
IE不支持<1%

全球支持率:约 97%

8.2 服务器支持

服务器支持版本配置方式
Nginx1.9.5+listen 443 ssl http2;
Apache2.4.17+Protocols h2 http/1.1
IIS10+默认支持
Node.js内置http2.createSecureServer()

8.3 Nginx 配置示例

nginx
server {
    listen 443 ssl http2;
    server_name example.com;
    
    ssl_certificate /path/to/cert.pem;
    ssl_certificate_key /path/to/key.pem;
    
    # TLS 1.2+ 配置
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
    ssl_prefer_server_ciphers off;
    
    # OCSP Stapling
    ssl_stapling on;
    ssl_stapling_verify on;
    
    location / {
        root /var/www/html;
    }
}

九、实际性能对比测试

9.1 测试环境

  • 服务器:Nginx 1.24,2 核 4G
  • 网络:100Mbps,延迟 50ms
  • 测试页面:30 个资源文件(HTML、CSS、JS、图片)

9.2 测试结果

指标HTTP/1.1HTTP/2提升
页面加载时间3.2s1.8s44%
请求数3030-
连接数6183%
总传输大小1.2MB1.1MB8%
首次渲染时间1.5s0.8s47%

9.3 性能提升明显的场景

场景提升幅度
多资源加载30-50%
高延迟网络40-60%
小文件多请求50-70%
大文件单请求5-10%

十、HTTP/2 的局限性

10.1 TCP 层队头阻塞

HTTP/2 在应用层解决了队头阻塞,但 TCP 层仍然存在:

数据包 1: [Frame1][Frame2][Frame3]
数据包 2: [Frame4][Frame5][Frame6]  ← 丢失

虽然 Frame4-6 与 Frame1-3 属于不同流,
但 TCP 要求按序交付,Frame4-6 丢失会阻塞后续所有数据

10.2 服务器推送效果不如预期

  • 难以准确预测客户端需要的资源
  • 推送的资源可能已在缓存中
  • Chrome 已计划移除 HTTP/2 Server Push 支持

10.3 连接迁移问题

TCP 连接基于四元组(源IP、源端口、目标IP、目标端口),网络切换时连接会断开。

HTTP/3 的解决方案

HTTP/3 使用 QUIC 协议(基于 UDP),解决了:

  • TCP 层队头阻塞
  • 连接迁移问题
  • 更快的握手(0-RTT)

十一、总结

特性HTTP/1.1HTTP/2HTTP/3
传输协议TCPTCPQUIC (UDP)
头部压缩HPACKQPACK
多路复用
队头阻塞TCP层有
服务器推送有(有限)
连接迁移不支持不支持支持

要点总结

  1. HTTP/2 通过多路复用解决了 HTTP 层队头阻塞
  2. HPACK 头部压缩显著减少了传输开销
  3. 二进制分帧让数据传输更高效
  4. 服务器推送效果有限,实际使用较少
  5. HTTP/2 必须配合 HTTPS 使用(浏览器要求)
  6. HTTP/3 使用 QUIC 解决了 TCP 层队头阻塞