一、HTTP缓存机制的基本概念
本质:对于一些具有重复性的HTTP请求,他们请求得到的数据都是一样的,我么们可以把这对【请求-响应】的数据缓存在本地,那么下次就直接读取本地的数据,不必在通过网络获取服务器的响应了。这样减少了客户端与服务器的交互次数,提升响应速度,降低服务器负载。
参与角色
- 缓存层:浏览器、CDN、代理服务器(决定是否直接使用本地缓存)。
- 源服务器:提供原始资源(决定缓存是否失效、是否需要更新)。
HTTP缓存有两种实现方式,分别是强制缓存和协商缓存。
二、强制缓存
强制缓存生效的核心是缓存未过期+无禁用强缓存指令,二者缺一不可,任意条件不满足则进入协商缓存流程。
| Cache-Control: max-age=60 | 相对时间,缓存有效时长60秒 | 高 |
| Cache-Control: s-maxage=300 | 专给共享缓存(CDN)的保质期,300秒 | 高 |
| Expires: Thurs, 15 Jan 2026 09:30:00 GMT | 绝对时间(HTTP/1.0遗产) | 低 |
1.计算缓存新鲜期(TTL)
新鲜期是缓存的“保质期”,取值遵循优先级顺序,且区分客户端与代理服务器:
(1) 代理服务器(如CDN):优先读取响应头的 s-maxage (单位:秒),仅对代理生效,优先级最高。
(2) 客户端服务器:若响应头无 s-maxage,读取max-age(单位:秒),优先级次之。
(3) 兜底方案:若以上两个字段都不存在,读取 Expires 字段(格式为GMT绝对时间),计算 Expires – 当前客户端时间 得到新鲜期 ;该方式受客户端本地时间影响,优先级最低。
2.计算缓存当前年龄
缓存当前年龄 = 当前时间 – 缓存存入时间
- 缓存存入时间的标准取值:响应头的 Date 字段(服务器返回响应的时间),而非客户端本地缓存的存储时间。
- 补充:若响应头有 Age 字段(通常由上游共享缓存添加),则当前年龄的初始值会优先取 Age(可能覆盖基于 Date 的计算),再加上当前缓存层的驻留时间。
3. 强缓存生效的完整条件
- 时间条件:缓存当前年龄 < 缓存新鲜期。
- 指令条件:响应头无 no-cache、no-store 等禁用强缓存指令:no-cache(强制跳过强缓存,直接进入协商缓存);no-store(完全禁止缓存,每次都从服务器请求最新资源)。
若上述任一条件不满足,强缓存失效,触发协商缓存。
三、协商缓存
核心逻辑是客户端携带缓存标识向服务器验证资源是否更新,服务器返回“有效”则复用资源,返回“无效”则拉取新资源。
触发条件:1.强制缓存失效; 2.客户端主动刷新页面。
1.协商缓存的两组核心字段
| ETag: “v2-abcd” | If-None-Match: “v2-abcd” | 服务器对比ETag值,一致则返回304 |
| Last-Modified: Thurs, 15 Jan 2026 10:00:00 GMT | If-Modified-Since: Thurs, 15 Jan 2026 10:00:00 GMT | 服务器检查资源最后修改时间,未变更则返回304 |
协商缓存的标识分为 HTTP/1.1 优先级更高的 ETag 组 和 HTTP/1.0 的 Last-Modified 组,两组字段配对使用。
- 服务器端响应字段(第一次请求时返回): ETag: “xxx”
- 含义:资源的唯一标识(通常是资源内容的哈希值),资源内容只要修改, ETag 就会变化。
- 优势:能识别内容的细微修改(如文件改了一个字符),弥补 Last-Modified 的精度缺陷。
- 客户端请求字段(第二次请求时携带): If-None-Match: “xxx”
- 含义:携带第一次请求拿到的 ETag 值,传给服务器做比对。
- 服务器端响应字段(第一次请求时返回): Last-Modified: Thurs, 15 Jan 2026 10:00:00 GMT
- 含义:资源最后一次修改的时间,精确到秒。
- 缺陷:无法识别 1 秒内的多次修改;文件内容未变但修改时间变了(如重新保存),会误判为资源更新。
- 客户端请求字段(第二次请求时携带): If-Modified-Since: Thurs, 15 Jan 2026 10:00:00 GMT
- 含义:携带第一次请求拿到的 Last-Modified 值,传给服务器做比对。
2.协商缓存的判断流程(服务器侧)
- 若 If-None-Match 值 = 服务器当前资源的 ETag 值 → 资源未更新 → 返回 304 Not Modified 响应(无响应体,仅响应头),客户端复用本地缓存。
- 若不相等 → 资源已更新 → 返回 200 OK 响应(携带新资源和新的 ETag / Last-Modified ),客户端更新本地缓存。
- 若 If-Modified-Since 时间 ≥ 服务器当前资源的最后修改时间 → 资源未更新 → 返回 304。
- 若小于 → 资源已更新 → 返回 200 并携带新资源。
四、服务器如何生成“保质期”与“指纹”
- 静态资源(如图片、JS):设置较长 max-age (如 max-age=86400 ,1天)。
- 动态资源(如接口):设置 no-cache 或 max-age=0 ,强制走协商缓存。
- CDN资源:通过 s-maxage 单独设置共享缓存的保质期。
- ETag :服务器对资源内容计算哈希(如MD5、SHA1),或使用文件版本号。
- Last-Modified :服务器读取文件的最后修改时间,转换为GMT格式返回。
五、一些面试问题
- 强缓存不请求服务器,0 RTT;协商缓存必须请求服务器,1 RTT(返回304则不传输资源)。
- 强缓存靠 Cache-Control/Expires 判断;协商缓存靠 ETag/Last-Modified 校验。
- Last-Modified精度为秒,无法识别1秒内的多次修改;ETag基于内容哈希,能精准识别内容变化。
- 某些场景下文件内容未变,但修改时间会改变时(如重新上传),此时Last-Modified会误判,ETag不变,不会触发不必要的资源重新请求。
无响应体,传输体积小,节省宽带;客户端会更新缓存的 Date 字段,重新计算缓存年龄。
网硕互联帮助中心



评论前必须登录!
注册