# HTTP 缓存
- 缓存的规则
- 缓存的方案
- 缓存的优点
- 不同刷新的的请求执行过程
# 缓存规则
用于缓存 JS、css、图片等资源,根据缓存阶段,分为两个强制缓存、协商缓存
强缓存
和协商缓存
同时存在,强缓存优先级高于协商缓存执行强缓存时,若命中,则直接使用缓存数据库数据 (即本地数据),不在进行缓存协商。
# 强制缓存
强缓存下,命中规则
+------------+ +------------+
| 客户端 | ------request----------> | 缓存数据库 |
+------------+ +------------+
| |
| |
+------------+ +------------+
| 缓存数据库 | <--有缓存,且为失效,返回数据 | 客户端 |
+------------+ +------------+
问题:此时如何判断失效?
强缓存,为命中
+------------+ +------------+ +------------+
| 客户端 | ------ request ----> | 缓存数据库 | | 服务器 |
+------------+ +------------+ +------------+
| | |
| <------------ invalid ------------ | |
| |
| --------------------- request --------------------> |
| |
| <-------- response Data and cache rule ------------ |
| |
| --------- saved cache rule to local db ------------ |
问题:此时的 cache rule 是什么?
# 协商缓存
客户端,从缓存数据库中获得到缓存数据的标识,得到标识后发起 request 到服务器,询问是否最新的?
- 如果没有失效,服务器,返回
304
,客户端直接从缓存中获得所请求的的数据?- (比如不加后缀的,即哈希值,容易返回
304
)
- (比如不加后缀的,即哈希值,容易返回
问题:此时所说的 客户端直接从缓存中获得所请求的的数据
是从浏览器的那个缓存数据库吗?那为什么有些 304
显示 memory cache
或 disk cache
,有些 304
则显示具体的 size
大小呢?
协商缓存下,命中规则
+------------+ +------------+ +------------+
| 客户端 | | 缓存数据库 | | 服务器 |
+------------+ +------------+ +------------+
| | |
| ---------- 获取缓存数据的标识 ------> | |
| |
| <---------- 返回缓存数据的标识 ------ |
| |
| ----- 请求服务器验证缓存标识对应的数据是否已失效 --------> |
| |
| <-------------- 通知客户端缓存还未失效 ---------------- |
|
| -------------- 获取缓存数据---------> |
协商缓存下,未命中规则
+------------+ +------------+ +------------+
| 客户端 | | 缓存数据库 | | 服务器 |
+------------+ +------------+ +------------+
| | |
| ---------- 获取缓存数据的标识 ------> | |
| |
| <---------- 返回缓存数据的标识 ------ | |
| |
| ----- 请求服务器验证缓存标识对应的数据是否已失效 --------> |
| |
| <-------------- 返回最新数据和缓存的规则 -------------- |
| |
| ----- 将数据和规则都存入到系统 -------> | |
# 缓存方案
在强缓存阶段: 客户端发起 HTTP 请求,主要是通过以下两个字段来与服务器获得缓存请求更换的。
Cache-control:
cache-control: max-age=600
max-age=600
,表示缓存的内容在 600 秒后失效private
:客户端可以缓存public
:客户端和服务器都可以缓存max-age=t
:缓存的内容将在t
秒后失效no-cache
:需要使用协商缓存来验证缓存数据no-store
:所有内容都不缓存Cache-Control: no-store, no-cache, no-transform, must-revalidate, max-age=0
:比如sockjs-node/info?t=1610684159275
中的请求
Expires:
expires: Fri, 15 Jan 2021 03:04:40 GMT
- 返回服务器返回的数据的到期时间
- 当再次请求时的请求时间小于返回的此时间,则直接使用缓存数据。(问题:此时的从什么地方使用缓存?服务器?客户端?)
- 旧时代产物,由于时间 BS 时间误差,现在用
cache-control
替代
在协商缓存阶段:
协商缓存,即和服务器进行协商。浏览器发起 HTTP 请求后,服务器将缓存标识和数据一起给客户端。客户端备份至自己的缓存中。
再次请求后,将带有的缓存标识也一并发给服务器,服务器据此作出判断,未失效则 304
,客户端拿到该状态码直接使用缓存数据。
ETag:
ETag: W/"5ffefa99-834c"
:服务器告诉浏览器当前资源在服务生成唯一标识。- ETag 比较昂贵,占用服务器资源。
- If-None-Match:
- 不同:说明资源被改动过,整体返回响应体,
200
- 相同:资源 w 无心修改,直接读取客户端的缓存,响应
304
- 不同:说明资源被改动过,整体返回响应体,
Last-modified:
Last-modified: Wed, 13 Jan 2021 13:50:17 GMT
- 服务器在响应时,会告诉浏览器资源的最后修改时间。
- (问题,这个时间如何判断?)
If-Modified-since
:浏览器再次请求服务器的时候,请求头会包含此字段修改才下载- 与最后修改时间对比,一致返回
304
- 从这个时间开始算起
- 被修改:传输响应整体,
200
Ok - 未修改:只传输响应 header,
304
Not Modified
- 与最后修改时间对比,一致返回
If-Unmodified-Since
:从这个事件算起,是否文件没有被更改?属于未修改才下载- 被修改:不传输,服务器返回,
412
Precondition failed (预处理错误) - 未修改:继续传输文件,
200
Ok
- 被修改:不传输,服务器返回,
在强缓存阶段:服务器响应的 header 中 Expires(逾期)
、Cache-Control
表示。
上图中,百度首页,有两个文件 (cd37ed75a9387c5b.js
、d
) 将 Cache-control
设置为极低:max-age=3600
甚至不设置。
而其他则设置极高 Cache-control: max-age=2592000
,测试则从 memory-cache
中加载
# 缓存优点
- 减少冗余的数据传输,节省宽带流量
- 减少服务器负担,提高网站性能
- 加快客户端加载网页的速度。
# 其他特性
- F5,去看看文件过期了没有?请求带上
If-Modify-since
,但是现在很多网站的没有这个字段 - CTRL+F5,先删除缓存文件,再去服务器请求完整资源文件,强迫客户端强制执行首次更新拉取最新的资源,不缓存
# 总结
- 强缓存:
Cache-control
、Expires
- 协商缓存:
last-modified
、eTag
Cache-Control:max-ege:600
: 在600s
后,请求这个文件才重新请求服务器Expires
:Expires
= max-age + 请求时间,需要与last-modified
配合- 过期时间前,可以从浏览器缓存取数据,无需请求
# TODO:问题
- HTTP 的服务器是如何缓存数据的?
cache-control:max-age=10
,10s
后如何处理后续的缓存工作?协商缓存是什么?
强缓存是什么?
是怎么判断本地有缓存的?- Chrome 勾选了
Disable Cache
,禁用缓存
- 顺序:
强缓存(——> 协商缓存(Cache-Control
、Expires
)last-modified
、ETag
)。 直接进入协商缓存
- Chrome 取消勾选了
Disable Cache
- 顺序: 强缓存(
Cache-Control
、Expires
) ——> 协商缓存(last-modified
、ETag
) - 此时直接从
memory
或disk
中读取存储的缓存