什么是 HTTP 缓存?
HTTP 缓存是指浏览器/客户端在向服务器发送 HTTP 请求后,将请求与响应的数据缓存到本地。当下次请求相同的资源时,浏览器可以直接从本地读取缓存数据,而无需再次从服务器获取,从而提升性能并减少网络请求。
HTTP 缓存主要分为两种实现方式:
- 强制缓存
- 协商缓存
一、强制缓存
定义:
强制缓存是由浏览器单方面决定是否使用本地缓存的一种机制。只要缓存未过期,就直接使用本地缓存,不向服务器发起请求。
实现方式:通过响应头字段控制
1. Cache-Control
推荐使用的标准缓存控制机制(HTTP/1.1)
常用指令说明:
指令 | 含义 |
---|---|
private | 仅客户端可以缓存 |
public | 客户端和代理服务器都可以缓存 |
max-age=xxx | 缓存的相对过期时间(单位:秒) |
no-cache | 使用协商缓存验证 |
no-store | 禁止缓存 |
示例:
Cache-Control: private; max-age=6000
表示该资源只能由客户端缓存,并将在 6000 秒后过期。
2. Expires
用于指定资源的绝对过期时间(HTTP/1.0 的遗留字段)
示例:
Expires: Mon, 07-Oct-2024 08:20:35 GMT
表示该资源在客户端时间 07-Oct-2024 08:20:35
过期。
缺点:依赖客户端本地时间,容易因时钟差异导致缓存失效或误用。
强制缓存对比总结:
对比项 | Cache-Control | Expires |
---|---|---|
时间类型 | 相对时间(以请求时间为起点) | 绝对时间(具体日期时间) |
灵活性 | 支持多种参数,功能丰富 | 只能设置过期时间 |
兼容性 | HTTP/1.1 标准 | HTTP/1.0 遗留字段 |
二、协商缓存
定义:
当强制缓存失效后,客户端会向服务器发送请求,由服务器判断资源是否更新,这种缓存机制称为协商缓存。
实现方式:通过Cache-Control + 请求头 + 响应头 + 304 Not Modified 实现
1. If-Modified-Since
/ Last-Modified
流程说明:
-
第一次请求时,服务器返回资源,并在响应头加上:
Last-Modified: <资源最后修改时间>
-
客户端后续请求时,带上:
If-Modified-Since: <上次的 Last-Modified 时间>
-
服务器比较时间:
- 如果资源已修改 → 返回状态码
200
和新数据 - 如果资源未修改 → 返回状态码
304 Not Modified
,客户端读取本地缓存
- 如果资源已修改 → 返回状态码
2. If-None-Match
/ ETag
流程说明:
-
第一次请求时,服务器返回资源,并在响应头加上:
ETag: "<资源唯一标识符>"
-
客户端后续请求时,带上:
If-None-Match: "<上次的 ETag>"
-
服务器比较 ETag:
- 如果不一致 → 返回状态码
200
和新数据 - 如果一致 → 返回状态码
304
,客户端读取缓存
- 如果不一致 → 返回状态码
协商缓存优先级:
如果一个请求同时包含 If-None-Match
和 If-Modified-Since
,服务器会优先使用 If-None-Match
判断。
两种协商缓存方式对比:
对比项 | Last-Modified / If-Modified-Since | ETag / If-None-Match |
---|---|---|
判断依据 | 资源最后修改时间 | 资源唯一标识(哈希值等) |
精确度 | 有时间精度限制(如秒级) | 高,支持更细粒度的变更识别 |
强制缓存与协商缓存对比
类型 | 控制方 | 是否发请求 | 主要头部字段 | 特点说明 |
---|---|---|---|---|
强制缓存 | 浏览器单方面 | ❌ 不发请求 | Cache-Control 、Expires | 快速响应,提升性能 |
协商缓存 | 服务器决定 | ✅ 发请求 | If-Modified-Since / Last-Modified If-None-Match / ETag | 确保资源新鲜性,兼顾准确性和性能 |