Skip to content

概念卡片: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 为准。

关联

最近更新