主题
概念卡片:HTTP 缓存与版本演进
一句话机制:HTTP 缓存分强缓存(浏览器判断没过期就直接用本地缓存)和协商缓存(过期后带条件字段问服务器,304 则继续用缓存);版本演进的本质是解决队头阻塞——HTTP/1.1 用长连接解决连接开销,HTTP/2 用多路复用解决 HTTP 层队头阻塞,HTTP/3 换 UDP 上的 QUIC 解决 TCP 层队头阻塞。
强缓存 vs 协商缓存
| 强缓存 | 协商缓存 | |
|---|---|---|
| 判断方 | 浏览器(主动) | 服务器(协商) |
| 字段 | Cache-Control(相对)/ Expires(绝对) | If-Modified-Since↔Last-Modified;If-None-Match↔ETag |
| 命中结果 | 直接用缓存(from disk cache) | 304 Not Modified → 用缓存 |
- Cache-Control 优先级高于 Expires(前者更精细)。
- ETag 优先级高于 Last-Modified:ETag 能解决「内容没变但 mtime 变」「秒级内修改」「服务器拿不到精确 mtime」三个问题。
- 协商缓存字段需配合 Cache-Control 使用:只有未命中强缓存,才会发带协商字段的请求。
HTTP 版本演进
| 版本 | 关键改进 | 遗留问题 |
|---|---|---|
| HTTP/1.0 | 每请求新建 TCP(短连接) | 连接开销大 |
| HTTP/1.1 | 长连接 + 管道传输 + 更多缓存/状态码 | 响应队头阻塞(未解决) |
| HTTP/2 | 头部压缩(HPACK)+ 二进制帧 + Stream 多路复用 + 服务器推送 | TCP 层队头阻塞 |
| HTTP/3 | 换 UDP + QUIC(无队头阻塞 + 1-RTT/0-RTT + 连接迁移) | 网络设备不识 QUIC,普及慢 |
队头阻塞的层层演进
- HTTP/1.1 管道:解决请求的队头阻塞,但服务器按序响应 → 响应队头阻塞仍在。
- HTTP/2 多路复用:一个 TCP 连接承载多个 Stream(Stream ID 区分,帧可乱序)→ 解决 HTTP 层队头阻塞。
- 但 TCP 是字节流,要求数据连续:前一个字节没到,后面的只能堆在内核缓冲区 → TCP 层队头阻塞。
- HTTP/3(QUIC):某流丢包只阻塞该流,其他流不受影响;QUIC 用连接 ID 而非四元组标记连接 → 支持连接迁移。
关键代码/字段示例
Cache-Control: max-age=3600 # 强缓存,相对时间(秒)
Expires: Wed, 21 Oct 2026 07:28:00 # 强缓存,绝对时间
ETag: "33a64df551425fcc55e4d42a148795d9f25f89d4"
If-None-Match: "33a64df551425fcc55e4d42a148795d9f25f89d4"不变量(必须成立的约束)
- 强缓存命中不会发请求;协商缓存命中会发请求但返回 304。
- 优先级:Cache-Control > Expires;ETag > Last-Modified。
- HTTP/2 客户端建 Stream 用奇数 ID,服务器用偶数 ID。
- HTTP/3 的 QUIC 内部包含 TLS,握手 1 RTT,会话恢复可 0-RTT。
常见误解
- 以为「HTTP/2 彻底解决了队头阻塞」→ 只解决 HTTP 层,TCP 层丢包仍会阻塞所有请求。
- 以为「304 是重定向」→ 304 与跳转无关,是「资源未修改、用缓存」。
- 以为「Cache-Control 和 Expires 并列」→ Cache-Control 优先,二者同时存在时以 Cache-Control 为准。
关联
- HTTP 报文:概念卡片:HTTP协议与报文
- 总览:计算机网络技术栈总览