HTTP/1.1、HTTP/2 与 HTTP/3
HTTP 的三代演进都在解决同一个问题:一条连接上的请求/响应模型太浪费。本章讲持久连接、HTTP/2 的多路复用与头部压缩、HTTP/3 基于 QUIC 的消除队头阻塞,以及缓存控制与 REST 的约束。
请求/响应模型
Section titled “请求/响应模型”HTTP 是无状态的请求/响应协议:客户端发请求(方法、路径、头),服务器回响应(状态码、头、体)。无状态(每个请求独立)让水平扩展容易(→ 系统设计工具箱),会话状态交给 Cookie 与令牌(→ 认证与授权)。
HTTP/1.0 → 1.1:连接复用
Section titled “HTTP/1.0 → 1.1:连接复用”- HTTP/1.0:每个请求一条 TCP 连接——三次握手 + 慢启动(→ 传输层:TCP 与 UDP)每个请求都付一遍,浪费;
- HTTP/1.1:**持久连接(keep-alive)**复用连接 + **管线化(pipelining)**连续发请求——但响应必须按序返回,队头阻塞让管线化形同虚设。浏览器的实际解法:每域名 6 条并行连接——把队头阻塞摊薄到 6 条线。
HTTP/2:二进制 + 多路复用
Section titled “HTTP/2:二进制 + 多路复用”同一个 TCP 连接上多路复用多个流:帧化(二进制分帧)、流优先级、头部压缩(HPACK)——1.1 时代每个请求重复发几百字节的头,2.0 用字典 + 增量编码压缩到几十字节。
HTTP/2 的多路复用仍受 TCP 队头阻塞:所有流共享一条 TCP 连接,一个 TCP 包丢了,所有流都要等重传(→ 传输层:TCP 与 UDP)。2.0 在丢包严重的网络上可能比 1.1 的 6 条连接更慢。
HTTP/3:QUIC 上的 HTTP
Section titled “HTTP/3:QUIC 上的 HTTP”HTTP/3 = HTTP over QUIC:每个流独立重传,流间不再互相阻塞;握手与 TLS 合并(1-RTT 甚至 0-RTT);连接迁移(换网络不断线)。HTTP/3 在丢包网络上优势明显;良好网络上与 H2 差距小(拥塞控制相同)。
| HTTP/1.1 | HTTP/2 | HTTP/3 | |
|---|---|---|---|
| 连接 | 每域名 6 条 | 1 条 | 1 条(QUIC/UDP) |
| 多路复用 | 无(队头阻塞) | 有(TCP 队头阻塞) | 有(流独立) |
| 头部 | 明文重复 | HPACK 压缩 | QPACK 压缩 |
| 传输 | TCP | TCP | QUIC(UDP) |
缓存头是性能优化的第一杠杆——最快的请求是不发生的请求:
- 强缓存:
Cache-Control: max-age=3600(新鲜期内不发请求);immutable(永不变化的内容,如带哈希的静态资源); - 协商缓存:
ETag/If-None-Match、Last-Modified/If-Modified-Since——过期后问服务器"变了吗",没变回 304(不带体); - CDN:边缘缓存(→ 系统设计工具箱),
Cache-Control: s-maxage控制边缘,Vary控制键。
静态资源的标准模式:文件名带内容哈希 + immutable 长缓存——变更即改名,缓存永不失效。
REST 的约束
Section titled “REST 的约束”REST 是一组架构约束,不是协议:无状态、统一接口(资源的名词 + 方法的动词:GET/POST/PUT/DELETE)、可缓存、分层系统。回报是可扩展性与缓存友好;代价是"动作丰富的业务"塞进 CRUD 的别扭(用子资源与状态机表达)。GraphQL 与 RPC 是替代路线:前者按需取数(解决过度/不足取数),后者按动作建模——选择看接口的消费方是谁。
- HTTP/1.1 用 6 条并行连接摊薄队头阻塞;HTTP/2 的多路复用仍受 TCP 队头阻塞
- HTTP/3 基于 QUIC 消除队头阻塞,丢包网络上优势明显;握手与 TLS 合并
- HPACK/QPACK 头部压缩:从每请求几百字节到几十字节
- 缓存头是性能优化的第一杠杆:强缓存(max-age/immutable)+ 协商缓存(ETag/304)
- 静态资源模式:文件名带哈希 + immutable;REST 的回报是可扩展与缓存友好