客户端发出HTTP请求之后,客户端返回的响应头中可以用Pragma、Expires和Cache-Control字段表示是否使用http缓存,为什么需要HTTP缓存呢,当你多次请求同样的数据时,会产生很多不必要的浪费,因此用缓存之后只需要把数据存储在客户端本地,在需要的时候直接从本地调用即可
- Pragma:(HTTP1.0常用的一个字段)pragma包含两个字段,除了自身还有Expires,已经逐步退出历史舞台,偶尔会为了向下兼容时使用,值为no-cache,表示禁用缓存,和cache-control中的no-cache不一样。
- Expires:(HTTP1.0常用的一个字段)给定一个时间,如果在这个时间内申请数据则直接从本地缓存加载,超出这个时间才使用http请求。这个方法有非常大的缺陷,要求服务器和客户端保持严格的时间同步,而且时间过期之后服务器还要重新设置时间。
-
Cache-Control:(HTTP1.1新引入的字段)有private、public、max-age、no-cache和no-store几个常见属性值。
private:客户端可以缓存
public:客户端和代理服务器都可以缓存
max-age=XXX:缓存的内容将在XXX秒后失效
no-cache:对比缓存
no-store:强制缓存(不触发对比缓存)(优先级最高)
public 和 private 的选择
如果你用了CDN,你需要关注下这个值。CDN厂商一般会要求Cache-Control的值为public,提升缓存命中率。如果你的缓存命中率很低,而访问量很大的话,可以看下是不是设置了private,no-cache这类的值。如果定义了max-age,可以不用再定义public,它们的意义是一样的。
no-cache 缓存检验
当使用 no-cache 对比缓存时,HTTP 响应会返回 Last-Modified 和 Etag 这两个字段,服务端返回数据时,会通过 Last-Modified 把数据的最终修改时间返回到客户端。
过程如下:
服务端响应头:Last-Modified,Etag,可能还有 Expires 和 Cache-Control
客户端请求头:If-Modified-Since,If-None-Match
- 客户端请求一个页面 A
- 服务器返回页面 A,并在给A加上 Last-Modified、ETag 、Expires 和
Cache-Control: no-cache max-age = xxxx
- 客户端展现该页面,并将页面连同这些重要的请求头数据一起存入缓存。
- 客户再次请求页面 A,根据 max-age 判断是否数据是否还有效,如果有效就直接从内存中读取,如果失效则将上次请求时服务器返回的 Last-Modified、ETag 转成 If-Modified-Since、If-None-Match 传递给服务器。
- 服务器根据 If-Modified-Since、If-None-Match 来判断该页面自上次客户端请求之后是否被修改,如果没有被修改则直接返回
304
状态码和一个空的响应体,如果修改了则返回200
状态码和新的页面 A。


缓存命中顺序
- 最先的Expires和Catch-Control
Expires:客户端和服务端绝对时间
Catch-Control(优先级更高):客户端本地计数比较 - 其次Last-Modified和If-Modified-Since
Last-Modified:服务端时间
If-Modified-Since:客户端时间
缺点:
(1)服务端有时候和客户端时间不同步
(2)有时候一秒内改几次
(3)有时候服务端资源变化了但是Last-Modified没改 - 然后Etag和If-None-Match(优先级高于2)
Etag(entity tag):服务端通过对资源进行特殊编码生成的唯一校验码,资源变化都会导致ETag变化
If-None-Match:服务端上次传来的Etag
浏览器请求时的大致过程描述如下:
浏览器发出http请求前,先根据Cache-Control和Expired 字段判断缓存是否过期(两个字段同时存在的情况下,根据Cache-Control判断,该字段不存在时根据Expired判断)。如果没有过期,浏览器不发出http请求,直接从硬盘缓存中读取资源;如果已过期,则进行第2步逻辑;
向服务器发出http请求,其中request headers上会携带If-none-match和If-Modified-since字段,服务器收到请求后,会将If-none-match字段和本地的资源的ETag进行比较,如果二者不相等,则资源已更新,会返回200状态码和资源数据,响应头也会带上最新的资源ETag;如果二者相等,则命中缓存,返回304,浏览器收到响应后会读取本地缓存资源。如果If-none-match字段不存在,服务器会根据if-Modified-since字段进行比对资源的最后修改时间,处理逻辑基本和If-none-match一致。

参考:
[1].彻底理解浏览器缓存机制
[2.]第7题-浏览器缓存命中策略
网友评论