HTTP 1.0 vs 1.1 vs 2.0 vs 3.0 演进
从 1991 年的 HTTP/0.9 到今天的 HTTP/3,30 年间 HTTP 协议经历了四次重大版本迭代。
每次迭代都是为了解决前一个版本的痛点。理解这个演进过程,你就能理解现代 Web 技术的底层逻辑。
版本演进时间线
┌─────────────────────────────────────────────────────────────┐
│ HTTP 版本演进 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 1991 HTTP/0.9 单行协议,只有 GET │
│ │ │
│ │ 1996 HTTP/1.0 引入头部、POST、响应码 │
│ │ │
│ │ │ 1999 HTTP/1.1 持久连接、管道化、虚拟主机 │
│ │ │ │ │
│ │ │ │ 2015 HTTP/2 多路复用、header │
│ │ │ │ │ 压缩、服务器推送 │
│ │ │ │ │ │
│ │ │ │ │ 2022 HTTP/3 基于 QUIC │
│ │ │ │ │ │
│ └──┴──────────┴────┴───────────────────────────────► │
│ │
│ 时间线 │
│ │
└─────────────────────────────────────────────────────────────┘HTTP/0.9:一切的开始(1991)
特点
1. 极其简单,只有 GET 方法
2. 没有请求头、响应头
3. 只能传输 HTML
4. 无状态,无连接复用请求格式
GET /index.html
响应:
<html>
<body>Hello World</body>
</html>为什么 HTTP/0.9 被淘汰?
功能太少,无法满足复杂 Web 应用的需求。
HTTP/1.0:第一次扩展(1996)
新增特性
1. 引入请求头和响应头
2. 支持 POST 方法
3. 引入状态码
4. 支持多种内容类型(非仅限于 HTML)
5. 支持缓存(If-Modified-Since)请求格式
GET / HTTP/1.0
Host: www.example.com
User-Agent: Mozilla/4.0
Accept: text/html
响应:
HTTP/1.0 200 OK
Content-Type: text/html
Content-Length: 1234
Date: Tue, 24 Mar 2026 12:00:00 GMT
<html>...</html>HTTP/1.0 的问题
1. 每个请求都需要建立新 TCP 连接
2. 连接建立成本高(3 次握手)
3. 队头阻塞问题
4. 缓存机制不完善HTTP/1.1:最长寿的版本(1999)
核心改进
1. 持久连接(Keep-Alive)
2. 管道化(Pipelining)
3. 虚拟主机(Host 头)
4. 断点续传(Range 请求)
5. 更好的缓存机制1. 持久连接(Keep-Alive)
HTTP/1.0:
连接 ──── 请求1 ────> 关闭
连接 ──── 请求2 ────> 关闭
连接 ──── 请求3 ────> 关闭
每个请求都要 TCP 握手
HTTP/1.1:
Connection: keep-alive(默认)
连接 ──── 请求1 ────> 请求2 ────> 请求3 ────> 关闭
复用同一个 TCP 连接2. 管道化(Pipelining)
HTTP/1.0:
请求1 ────> 响应1 ────> 请求2 ────> 响应2 ────> ...
HTTP/1.1 管道化:
请求1 ────> 请求2 ────> 请求3 ────>
响应1 ────> 响应2 ────> 响应3 ────>
不用等响应就可以发下一个请求3. 虚拟主机(Host)
HTTP/1.0:IP 和域名一一对应
HTTP/1.1:一个 IP 可以托管多个网站,用 Host 头区分
GET / HTTP/1.1
Host: www.example.com ← 必不可少HTTP/1.1 的问题
1. 队头阻塞(Head-of-Line Blocking)
管道化中,如果请求1 响应慢,后面所有请求都要等
2. 头部重复
每次请求都要携带大量重复的头部
3. 单连接串行
为了避免队头阻塞,往往只用一个连接HTTP/2:多路复用(2015)
核心改进
1. 二进制分帧(Binary Framing)
2. 多路复用(Multiplexing)
3. Header 压缩(HPACK)
4. 服务器推送(Server Push)
5. 流控制1. 二进制分帧
HTTP/1.1(文本):
GET / HTTP/1.1
Host: example.com
HTTP/2(二进制帧):
┌───────┬─────────┬──────────┬─────────────────┐
│ Type │ Length │ Flags │ Stream ID │
├───────┴─────────┴──────────┴─────────────────┤
│ Payload │
└───────────────────────────────────────────────┘2. 多路复用
HTTP/1.1 问题:
一个页面有 10 个资源,浏览器只能开 4-6 个连接
连接 1: 资源1 ──────────> 资源1 <──────────
连接 2: 资源2 ───> 资源2 <─── 资源3 ───> ...
(队头阻塞)
HTTP/2 多路复用:
单个 TCP 连接 ──────────────────────────────────►
Stream 1 ── 帧 ──────────────────────>
Stream 2 ────────── 帧 ────────────────>
Stream 3 ─────────────────── 帧 ──────>
帧可以交错发送,互不阻塞3. Header 压缩(HPACK)
HTTP/1.1:每次请求都发送完整头部
GET / HTTP/1.1
Host: www.example.com
User-Agent: Mozilla/5.0
Accept: text/html
Accept-Language: zh-CN
Cookie: session_id=abc123; theme=dark
(重复的头部每次都发送)
HTTP/2 HPACK:只发送变化的 header
动态表 + 静态表 + 索引
头部体积减少 50%-90%4. 服务器推送(Server Push)
传统:浏览器请求 HTML → 服务器返回 HTML → 浏览器解析 → 发现 CSS → 请求 CSS
优化:服务器主动推送 CSS
HTTP/2 Push:
服务器 ──── PUSH_PROMISE (推送 CSS) ──> 浏览器
服务器 ──── HTTP/2 响应 (HTML) ──────> 浏览器
服务器 ──── HTTP/2 响应 (CSS) ────────> 浏览器(已经推送过了)HTTP/2 的问题
1. 队头阻塞问题转移到 TCP 层
- TCP 保证有序,一个包丢了,所有 Stream 都要等
2. TCP 连接需要时间建立
- TLS 握手 + TCP 握手 = 1-3 RTT
3. 移动网络切换困难
- 切换网络时,TCP 连接断开HTTP/3:QUIC 替代 TCP(2022)
核心改进
1. 基于 QUIC(UDP)
2. 0-RTT / 1-RTT 连接建立
3. 无队头阻塞的多路复用
4. 连接迁移(手机 WiFi → 4G)
5. 内置 TLS 1.3HTTP/3 vs HTTP/2
HTTP/2:
┌─────────────────────────────────────────────┐
│ HTTP/2 │
├─────────────────────────────────────────────┤
│ TLS 1.3 │
├─────────────────────────────────────────────┤
│ TCP │
├─────────────────────────────────────────────┤
│ IP │
└─────────────────────────────────────────────┘
HTTP/3:
┌─────────────────────────────────────────────┐
│ HTTP/3 │
├─────────────────────────────────────────────┤
│ QUIC │
├─────────────────────────────────────────────┤
│ UDP │
├─────────────────────────────────────────────┤
│ IP │
└─────────────────────────────────────────────┘HTTP/3 的优势
1. 延迟更低
- 1-RTT 建立连接
- 0-RTT 重连(缓存密钥)
2. 不受 TCP 队头阻塞影响
- Stream 级别独立
- 一个 Stream 丢包不影响其他 Stream
3. 连接迁移
- WiFi 切 4G 时保持连接
- Connection ID 不变各版本对比
| 特性 | HTTP/1.0 | HTTP/1.1 | HTTP/2 | HTTP/3 |
|---|---|---|---|---|
| 传输格式 | 文本 | 文本 | 二进制帧 | 二进制帧 |
| 多路复用 | 无 | 管道化(有问题) | 完整支持 | 完整支持 |
| 头部压缩 | 无 | 无 | HPACK | QPACK |
| 服务器推送 | 无 | 无 | 支持 | 支持 |
| 队头阻塞 | TCP 层 | TCP 层 | TCP 层 | Stream 级别 |
| 连接建立 | 3 RTT | 3 RTT | 2-3 RTT | 1-2 RTT |
| 传输层 | TCP | TCP | TCP | QUIC/UDP |
| TLS | 可选 | 可选 | 可选 | 内置 |
| 兼容性 | 旧 | 最广 | 新 | 最新 |
浏览器支持情况
HTTP/1.1:100% 支持
HTTP/2:95%+ 支持
HTTP/3:70%+ 支持(持续增长中)bash
# 查看网站是否支持 HTTP/2
curl -I --http2 https://www.example.com
# 查看网站是否支持 HTTP/3
curl -I --http3 https://www.example.com实际应用建议
1. HTTP/1.1 优化技巧
1. 减少请求数
- 合并 CSS/JS
- 图片雪碧图
- 内联小资源
2. 减少 cookie 传输
- 静态资源用独立域名(不带 cookie)
3. 启用压缩
- Accept-Encoding: gzip, br2. HTTP/2 的使用
nginx
# Nginx 启用 HTTP/2
server {
listen 443 ssl http2;
ssl_certificate cert.pem;
ssl_certificate_key key.pem;
}3. HTTP/3 的使用
nginx
# Nginx 启用 HTTP/3
server {
listen 443 quic reuseport;
ssl_certificate cert.pem;
ssl_certificate_key key.pem;
add_header Alt-Svc 'h3=":443"; ma=86400';
}面试追问方向
- HTTP/1.0 和 HTTP/1.1 的主要区别是什么?
- 什么是队头阻塞?HTTP/1.1 和 HTTP/2 是如何处理的?
- HTTP/2 的多路复用是什么原理?
- HTTP/2 和 HTTP/3 的主要区别是什么?
- 什么是 HTTP/2 的服务器推送?
- HPACK 是如何压缩头部的?
- 为什么 HTTP/3 选择基于 UDP 而不是 TCP?
- 什么是 0-RTT 和 1-RTT?
- 什么是 QUIC 协议?
- 如何在服务器上启用 HTTP/2 和 HTTP/3?
