跳到主要内容

HTTP/2 与 HTTP/3

问题

HTTP/2 和 HTTP/3 相比 HTTP/1.1 有哪些改进?QUIC 协议是什么?

答案

HTTP/2(2015)和 HTTP/3(2022)是 HTTP 协议的重大升级,解决了 HTTP/1.1 的性能瓶颈。

版本演进

核心对比

特性HTTP/1.1HTTP/2HTTP/3
传输层TCPTCPQUIC (UDP)
连接复用管道化(有限)多路复用多路复用
头部文本,重复发送二进制,HPACK 压缩QPACK 压缩
服务器推送
队头阻塞HTTP + TCP 层仅 TCP 层
加密可选推荐强制

HTTP/1.1 的问题

1. 队头阻塞

2. 头部冗余

# 每个请求都发送重复的头部
GET /page1.html HTTP/1.1
Host: example.com
User-Agent: Mozilla/5.0...
Accept: text/html
Accept-Language: zh-CN
Cookie: session=abc123

# 即使请求同一域名,头部也重复发送
GET /page2.html HTTP/1.1
Host: example.com
User-Agent: Mozilla/5.0... # 重复
Accept: text/html # 重复
Accept-Language: zh-CN # 重复
Cookie: session=abc123 # 重复

3. 连接限制

// 浏览器对同一域名的并发连接数限制
// Chrome: 6 个
// 黑科技:域名分片(domain sharding)
// cdn1.example.com, cdn2.example.com...

HTTP/2 特性

1. 二进制分帧

// HTTP/1.1: 文本协议
"GET /index.html HTTP/1.1\r\nHost: example.com\r\n..."

// HTTP/2: 二进制帧
// +-----------------------------------------------+
// | Length (24) |
// +---------------+---------------+---------------+
// | Type (8) | Flags (8) |
// +-+-------------+---------------+---------------+
// |R| Stream Identifier (31) |
// +-+---------------------------------------------+
// | Frame Payload |
// +-----------------------------------------------+

2. 多路复用

// 单个 TCP 连接处理所有请求
// 请求和响应可以交错发送
// 彻底解决 HTTP 层队头阻塞

3. 头部压缩(HPACK)

// HPACK 压缩原理
// 1. 静态表:61 个常见头部
// 2. 动态表:连接期间构建
// 3. 霍夫曼编码:压缩值

// 示例:
// 请求1: { ":method": "GET", ":path": "/", "host": "example.com" }
// 请求2: { 静态表索引: 2, 静态表索引: 4, 动态表索引: 62 }
// 头部从 ~800 字节 → ~20 字节

4. 服务器推送

// 服务器可以主动推送资源
// 客户端请求 HTML 时,服务器同时推送 CSS 和 JS

// 请求 index.html
// 服务器返回 index.html
// 服务器推送 style.css (PUSH_PROMISE)
// 服务器推送 app.js (PUSH_PROMISE)
# Nginx 配置示例
location / {
http2_push /style.css;
http2_push /app.js;
}
注意

服务器推送在实践中使用较少,Chrome 已在 2022 年移除支持。 替代方案:103 Early Hints、preload。

5. 流优先级

// 可以为流设置优先级和依赖关系
// 例如:HTML > CSS > JS > 图片

// 优先级树
// 根
// / \
// HTML 图片
// / \
// CSS JS

HTTP/3 与 QUIC

QUIC 协议

QUIC(Quick UDP Internet Connections)是 Google 开发的传输层协议。

HTTP/3 优势

1. 消除队头阻塞

// HTTP/2 问题:TCP 是字节流,一个包丢失阻塞所有流
// HTTP/3 解决:QUIC 流独立,丢包只影响单个流

2. 更快的握手

3. 连接迁移

// HTTP/2: 连接由四元组标识 (源IP, 源端口, 目标IP, 目标端口)
// Wi-Fi → 4G,IP 变化,连接断开,需要重新建立

// HTTP/3: 连接由 Connection ID 标识
// IP 变化不影响连接,无缝切换

4. 内置加密

// QUIC 强制加密
// 握手过程即完成加密协商
// 没有不加密的 QUIC

启用 HTTP/2 和 HTTP/3

Nginx 配置

# HTTP/2
server {
listen 443 ssl http2;
server_name example.com;

ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
}

# HTTP/3 (需要 Nginx 1.25+)
server {
listen 443 ssl;
listen 443 quic reuseport;
http2 on;

ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;

# 告知浏览器支持 HTTP/3
add_header Alt-Svc 'h3=":443"; ma=86400';
}

检测协议版本

// 浏览器 DevTools → Network → Protocol 列

// JavaScript 检测
const observer = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
if (entry.nextHopProtocol) {
console.log(`${entry.name}: ${entry.nextHopProtocol}`);
// h2 = HTTP/2
// h3 = HTTP/3
}
}
});
observer.observe({ type: 'resource', buffered: true });

常见面试问题

Q1: HTTP/2 相比 HTTP/1.1 有哪些改进?

答案

改进说明
多路复用单连接并行请求,解决队头阻塞
二进制分帧高效解析,减少错误
头部压缩HPACK 算法,减少传输量
服务器推送主动推送资源
流优先级重要资源优先传输

Q2: HTTP/2 还有什么问题?

答案

TCP 层队头阻塞

  • HTTP/2 解决了 HTTP 层队头阻塞
  • 但底层 TCP 仍然存在队头阻塞
  • 一个 TCP 包丢失会阻塞所有 HTTP/2 流

Q3: HTTP/3 如何解决队头阻塞?

答案

HTTP/3 使用 QUIC 协议(基于 UDP),流之间相互独立:

// QUIC 特性
// 1. 每个流独立,丢包只影响单个流
// 2. 不需要按顺序交付
// 3. 内置拥塞控制和重传机制
层级HTTP/2HTTP/3
应用层多路复用 ✅多路复用 ✅
传输层TCP 队头阻塞 ❌QUIC 无阻塞 ✅

Q4: QUIC 协议的特点?

答案

特性说明
基于 UDP用户态实现,快速迭代
0-RTT 恢复首次 1-RTT,恢复 0-RTT
无队头阻塞流独立,丢包不影响其他流
连接迁移Connection ID 标识,IP 变化不断连
内置加密强制 TLS 1.3
前向纠错可选的 FEC 减少重传

Q5: 前端如何利用 HTTP/2 优化?

答案

// 1. 停止使用雪碧图、合并文件
// HTTP/2 多路复用,小文件传输高效

// 2. 移除域名分片
// 单连接更高效,减少 DNS 和 TLS 开销

// 3. 合理使用服务器推送或 preload
// <link rel="preload" href="/critical.css" as="style">

// 4. 优化资源优先级
// <link rel="preload" ... fetchpriority="high">

// 5. 确保 HTTPS
// HTTP/2 实际上需要 HTTPS

相关链接