跳到主要内容

HTTP协议演进-1-2-3

1. 概念与原理

HTTP 是前端的母语,但 90% 前端只熟 HTTP/1.1 的语义层(method、status、header),对底层传输(多路复用、流控、队头阻塞)一知半解。这一篇把 HTTP/1.0 到 HTTP/3 的演进彻底讲透,让你能判断什么时候该开 HTTP/2、什么时候 HTTP/3 真有用、为什么 HTTP/2 没杀掉合并请求。

2. HTTP/0.9 到 HTTP/1.0

略过历史,记几个关键点:

  • HTTP/0.9(1991):只有 GET,没 header,纯文本
  • HTTP/1.0(1996):加了 header、method、status,每请求一个 TCP 连接

HTTP/1.0 致命缺陷:每个请求都要三次握手 + 慢启动,加载 10 张图 = 10 次握手。

3. HTTP/1.1(1997,至今主流)

3.1 持久连接 keep-alive

Connection: keep-alive
Keep-Alive: timeout=60, max=100

一个 TCP 连接发多个请求,省握手开销。HTTP/1.1 默认开启。

3.2 管道化(Pipelining)— 失败的尝试

允许客户端不等响应连续发请求,服务端按顺序返回。但队头阻塞问题严重:第一个请求慢,后面全等。浏览器全部默认关闭,实际等于没用。

3.3 队头阻塞(HoL,Head-of-Line Blocking)

HTTP/1.1 的根本问题:一个 TCP 连接上请求必须串行。慢请求拖慢所有后续。

浏览器的妥协:同一域名最多 6 个并行连接。所以才有"域名分片"(cdn1.x.com, cdn2.x.com)技巧。

3.4 分块传输 Transfer-Encoding: chunked

服务端不知道总长度时(流式生成、SSR),分块发送:

HTTP/1.1 200 OK
Transfer-Encoding: chunked

7\r\n
Mozilla\r\n
9\r\n
Developer\r\n
0\r\n
\r\n

每块 = 长度(hex)+ 内容。0\r\n\r\n 表示结束。Server-Sent Events、Streaming SSR 用这个。

3.5 Range / 断点续传

GET /video.mp4 HTTP/1.1
Range: bytes=1024-2047

HTTP/1.1 206 Partial Content
Content-Range: bytes 1024-2047/10485760
Content-Length: 1024

视频拖动进度条、下载断点续传、上传分片都靠这个。

3.6 缓存与协商缓存

类型含义
Cache-Control: max-age=3600强缓存客户端缓存 3600 秒,不发请求
Cache-Control: no-cache协商缓存必须发请求验证
Cache-Control: no-store不缓存完全不存
Cache-Control: private/public范围private 只浏览器、public 可被 CDN
Expires强缓存HTTP/1.0 老语法
ETag / If-None-Match协商内容指纹
Last-Modified / If-Modified-Since协商时间戳(精度只到秒)

详见模块 09。

3.7 Connection: close vs keep-alive

Connection: close # 响应后立即关 TCP
Connection: keep-alive # 保持连接复用

HTTP/1.1 默认 keep-alive,但服务端可以主动 close(防止连接占用)。

4. HTTP/2(2015,RFC 7540)

4.1 关键改进

特性HTTP/1.1HTTP/2
传输格式文本二进制(帧)
多路复用否(HoL)是(一个 TCP 多个流并发)
Header 压缩HPACK
服务端推送Server Push(已 deprecated)
优先级流优先级

4.2 二进制分帧

HTTP/2 把消息切成帧(frame),每帧带 stream ID。同一连接上多个 stream 的帧交错传输,接收方按 stream ID 重组。

连接 = TCP 连接
├── Stream 1(请求 1)
│ ├── HEADERS 帧
│ └── DATA 帧(多个)
├── Stream 3(请求 2,奇数客户端发起)
│ ├── HEADERS 帧
│ └── DATA 帧
└── Stream 5(请求 3)

抓包看:tcpdump + Wireshark 选 HTTP/2 协议解析,能看到 stream 交错。

4.3 多路复用解决了什么

一个域名一个 TCP 连接,承载所有请求。再也不用域名分片。

实测对比:100 个小资源加载:

  • HTTP/1.1:6 连接,每连接串行,约 100 / 6 个串行批次
  • HTTP/2:1 连接,全部并发

域名分片在 HTTP/2 时代有害:每个域名一个 TCP + TLS 握手,反而慢。需要把资源合并到一个域名。

4.4 HPACK 头压缩

HTTP/1.1 每个请求重发 cookie、UA、Accept 这些头(几 KB)。HPACK:

  • 静态表:常用头预定义编号(如 :method GET = 索引 2)
  • 动态表:连接内出现过的头存表,后续用索引引用
  • Huffman 编码:剩余字符串再压

实测压缩率 70-90%。但 HPACK 是有状态的(依赖动态表同步),不能跨连接复用,QUIC 因此换成 QPACK。

4.5 流优先级

客户端可以告诉服务端 stream 优先级(权重 + 依赖树)。浏览器据此让 HTML > CSS > JS > 图片优先返回。

但实际服务端实现差,Chrome 后来改用更简单的 Priority Hints(fetchpriority="high")。

4.6 Server Push(已废)

服务端主动推送资源(HTML 还没解析就推 CSS)。理论上省一个 RTT。但:

  • 浏览器实现复杂,缓存判断容易出错
  • 不知道客户端是否已有资源
  • Chrome 2022 移除支持

替代方案:HTTP 早期提示 103 Early Hints + Link rel=preload header。

4.7 TCP 队头阻塞依然存在

HTTP/2 解决了 HTTP 层 的队头阻塞,但 TCP 层的没解决:TCP 必须保证字节流有序,一个包丢失,后续所有 stream 都要等重传。弱网下 HTTP/2 可能比 HTTP/1.1 多连接更慢

这就是 HTTP/3 出现的根本原因。

4.8 启用 HTTP/2

Nginx:

server {
listen 443 ssl http2;
...
}

HTTP/2 实际部署强制要求 HTTPS(RFC 没规定,但浏览器都要 TLS)。

5. HTTP/3(2022,RFC 9114)

5.1 基于 QUIC

QUIC 是 Google 设计、IETF 标准化的传输层协议,基于 UDP。HTTP/3 就是 HTTP over QUIC。

层级HTTP/2HTTP/3
应用HTTP/2HTTP/3
安全TLS 1.2/1.3TLS 1.3(内置)
传输TCPQUIC
网络IPIP(UDP)

5.2 QUIC 的核心特性

真正消灭队头阻塞

QUIC 的 stream 独立可靠传输,一个 stream 丢包不影响别的 stream。HTTP/3 的多路复用是真的并行。

0-RTT 重连

首次连接:1-RTT 握手(TLS 1.3 + 传输参数)。复用 session:0-RTT,第一个包就带应用数据。

连接迁移

QUIC 用 Connection ID 标识连接,不依赖 IP+端口。手机从 WiFi 切 4G 时连接不断。

内置 TLS 1.3

不能用旧版 TLS,安全基线更高。

5.3 部署 HTTP/3

Nginx(1.25+ 支持):

server {
listen 443 ssl;
listen 443 quic reuseport; # UDP 443
http2 on;
http3 on;
add_header Alt-Svc 'h3=":443"; ma=86400'; # 通告 HTTP/3 可用
...
}

防火墙必须放行 UDP 443(很多公司只放 TCP 443)。

5.4 浏览器兼容

Chrome、Firefox、Edge、Safari 都已支持。首次访问还是 HTTP/2(不知道服务端支持 HTTP/3),看到 Alt-Svc 响应头后续请求切到 HTTP/3。

5.5 调试 HTTP/3

# curl 必须编译时开 HTTP/3 支持
curl --http3 -v https://cloudflare.com

# Chrome 看
# DevTools → Network → 右键列头加 "Protocol"
# h3 = HTTP/3, h2 = HTTP/2, http/1.1 = HTTP/1.1

6. 各版本性能对比

实际场景(首屏加载、100 个资源):

协议RTT队头阻塞弱网表现部署难度
HTTP/1.1高(多连接)严重中(多连接对冲)
HTTP/2TCP 层有弱网比 1.1 差中(要 TLS)
HTTP/3显著好高(UDP、新栈)

前端选型

  • 普通网站:HTTP/2 已足够
  • 移动端 / 海外 / 弱网用户多:HTTP/3 有显著收益
  • 流媒体 / 实时性敏感:HTTP/3

7. 关键头字段(前端必知)

7.1 请求头

用途
Host必填,虚拟主机分发
User-Agent浏览器标识
AcceptAccept-LanguageAccept-Encoding内容协商
Authorization认证
Cookiesession
OriginCORS 源
Referer来源页(拼写 typo,已成历史)
If-None-MatchIf-Modified-Since协商缓存
Range断点续传

7.2 响应头

用途
Content-Type响应 MIME
Content-Lengthbody 长度
Content-Encodinggzip / br
Cache-ControlETagLast-Modified缓存
Set-Cookie写 cookie
Access-Control-*CORS
Strict-Transport-SecurityHSTS
Content-Security-PolicyCSP
X-Frame-Options防 clickjacking
Alt-SvcHTTP/3 通告

7.3 状态码

5 类,每类前端必知典型:

  • 1xx:100 Continue、101 Switching Protocols(WebSocket)、103 Early Hints
  • 2xx:200、201 Created、204 No Content、206 Partial
  • 3xx:301(永久)、302(临时)、304 Not Modified、307/308(保留 method)
  • 4xx:400、401(未认证)、403(无权限)、404、405、409(冲突)、413(body 太大)、415、429(限流)
  • 5xx:500、502 Bad Gateway(上游错)、503 Service Unavailable、504 Gateway Timeout

401 vs 403:401 = 没登录(应去登录),403 = 已登录但无权限。前端处理逻辑不同。

302 vs 307:302 历史上有些浏览器会把 POST 改成 GET 重定向,307/308 严格保留 method。

8. 性能优化要点

8.1 减少 RTT

  • 用 HTTP/2 / 3 多路复用
  • 开 keep-alive
  • preconnect 提前握手
  • 0-RTT(HTTP/3 + TLS 1.3)

8.2 减少 body

  • gzip / brotli 压缩(brotli > gzip 约 20%)
  • 图片格式:WebP、AVIF
  • Tree shaking、按需加载

8.3 缓存

  • 静态资源 hash 文件名 + Cache-Control: max-age=31536000, immutable
  • HTML 用协商缓存 + 短 max-age

详见模块 09。

8.4 早期提示

HTTP/1.1 103 Early Hints
Link: </style.css>; rel=preload; as=style
Link: </app.js>; rel=preload; as=script

HTTP/1.1 200 OK
...

让浏览器在等 200 时就开始下载关键资源。Nginx 1.25.3+ 支持。

9. 故障排查

9.1 看用的什么协议

# curl
curl -v --http2 https://example.com 2>&1 | grep "HTTP/"

# Chrome DevTools → Network → Protocol 列

9.2 看请求耗时分解

Chrome DevTools → Network → 单击请求 → Timing:

  • Queueing:浏览器排队
  • Stalled:等连接
  • DNS Lookup
  • Initial connection(TCP)
  • SSL(TLS 握手)
  • Request sent
  • Waiting (TTFB):服务端处理
  • Content Download

TTFB 长 = 服务端慢。Stalled 长 = 浏览器并发限制(HTTP/1.1)或 keep-alive 失效。

9.3 502 / 504 区别

  • 502 Bad Gateway:代理(Nginx)收到上游不合法响应(连接被重置、上游崩)
  • 504 Gateway Timeout:代理等上游超时

9.4 426 Upgrade Required

服务端要求客户端升级协议。WebSocket 握手失败常见。

10. 安全考量

  • 强制 HTTPS:HTTP 明文,中间人随便看。HSTS preload 让浏览器永远走 HTTPS
  • 关 HTTP/1.0:老协议安全审计差
  • 限制 method:禁用 TRACE、CONNECT
  • 响应头加固:CSP、HSTS、X-Content-Type-Options、X-Frame-Options
  • gzip bomb:服务端解压请求 body 时限大小,防 100KB 压缩 → 1GB 解压

11. 常见反模式

  • HTTP/2 还在做域名分片:反而慢
  • HTTP/2 拼接 sprite:HTTP/2 多个小请求不再贵,sprite 反而失去按需加载
  • 大量小文件不开 HTTP/2:每个文件一次 TCP,慢得离谱
  • HTTP/3 不通告 Alt-Svc:客户端不知道,永远走 HTTP/2
  • HTTP/3 端口不放 UDP:防火墙拦截,客户端 fallback 回 HTTP/2
  • Cache-Control 写 no-cache 当不缓存:no-cache = 协商缓存,要写 no-store
  • 302 redirect 链 > 3 跳:每跳 RTT,性能差
  • Connection: close 在生产:丢失 keep-alive,QPS 折半

12. 延伸阅读