HTTP中的expires、cache-control与last-modified、etag

869 阅读5分钟

客户端缓存

客户端缓存是指客户端在本地保存用户最近请求过的数据,当用户再次访问时,客户端直接从本地磁盘加载数据。其可分为强缓存(本地缓存)和弱缓存(协商缓存)

强缓存:用户非首次访问资源与使用强缓存,那么在过期时间内不会从向服务端发起请求,而是直接从本地缓存中获取(不管资源是否变化)

协商缓存:用户非首次访问资源与使用协商缓存,需要向服务端发起请求,判断资源的最后修改时间或者资源的唯一标识是否修改,若未修改,返回状态码304,从缓存中获取;否则重新发起请求,并更新客户端缓存。

1、强缓存(强制缓存)

强缓存利用的是http响应头中的expires和Cache-Control

1-1 expires

这是HTTP/1.0的字段,是一个绝对时间(当前时间+缓存时间),如expires: Sun, 21 Nov 2032 23:43:27 GMT

设置这个字段后,在未过期之前不需要从服务端请求数据

缺点:由于是绝对时间,用户可修改客户端本地的时间,导致缓存失效;同时,时差或者误差也会导致客户端与服务端的时间不一致,导致缓存失效

1-2 Cache-Control

这是HTTP/1.1中新增的字段,表示资源缓存的最大有效时间,如cache-control: public, max-age=31536000

其包含一些常用的值

  1. private:仅客户端可以缓存(默认值);
  2. public:客户端和代理服务端都可以缓存;
  3. max-age=xxx:最大有效时间(单位秒);
  4. must-revalidate:如果超过了 max-age 的时间,客户端必须向服务端发送请求,验证资源是否还有效。
  5. no-cache:表示客户端可以缓存资源,但每次使用前都需要验证缓存资源的有效性,相当于 max-age=0,must-revalidate;
  6. no-store:不强缓存,也不协商缓存

对比:自HTTP/1.1开始, expires逐渐被Cache-Control取代。Cache-Control是一个相对时间,即使客户端时间发生改变,相对时间也不会随之改变,这样可以保证服务端与客户端的时间的一致性,同时,Cache-Control的可选择的配置项

强缓存来源可分成内存缓存和磁盘缓存 from mermory cache 是页面刷新的时候内存缓存中获取 from disk cache 是关闭Tab时从磁盘缓存中获取

例如非首次访问百度首页时,在控制面板中可以看到大部分资源返回状态码是 200 (from memory cache 内存缓存),其中Response Headers 返回了cache-control: max-age=2592000,这说明该资源走的是强缓存策略

image.png

2、协商缓存(对比缓存)

当强缓存失效,则使用协商缓存,由服务端决定缓存是否失效。协商缓存包含两组字段

2-1 Last-Modified & If-Modified-Since

Last-Modified表示的是文件的最后修改时间

交互流程

  1. 客户端发起GET请求
  2. 服务端接收、处理请求,返回响应头再,包含Last-Modified字段,客户端存储资源与该字段
  3. 当再次请求资源时,将缓存的 Last-Modified 的值写入到请求头的 If-Modified-Since 字段
  4. 服务端将If-Modified-Since的值与Last-Modified相比较,若相等,数据未修改,返回304状态码;否则,响应200,返回最新的数据和Last-Modified

2-2 Etag & If-None-Match

Etag存储的是文件的特殊标识,可以保证每个资源都是唯一的,资源变化会导致Etag变化

ETag的格式为:Etag= [ weak ] opaque-tag

类型
Etag="61a48a78-aba"强校验
Etag=W/"61a48a78-aba"弱校验(W大小写敏感)

Etag & If-None-Match的交互流程与Last-Modified & If-Modified-Since的交互流程一样 在交互上,Etag 对应 Last-Modified,If-None-Match 对应 If-Modified-Since

Etag主要为了解决 Last-Modified 无法解决的一些问题: 1、因为 Last-Modified 能检查到的粒度是秒级的,所以当服务端的更新资源速度是秒以下的,会导致获取不到最新的数据 2、如果文件是通过服务端动态生成的或者周期性更改,内容不变,仅仅是修改时间,这时候就起不到缓存的效果; 3、某些服务器不能精确的得到文件的最后修改时间;

Etag 的优先级高于 Last-Modified,大部分web服务器会默认开启协商缓存,同时开启【 Last-Modified & If-Modified-Since】和【Etag & If-None-Match】,确保缓存的可靠性。

例如非首次访问百度首页时,在控制面板中可以看到部分资源返回状态码是 304,其中Request Headers 和 Response Headers 出现了 ETag/If-None-Match、Last-Modified/If-Modified-Since字段,这说明该资源走的是协商缓存策略。

image.png

3、缓存位置

使用强缓存时,可以看到缓存的来源有from memory cache(内存缓存)与disk cache(磁盘缓存),指的就是缓存所在的位置。请求一个资源,会按照优先级依次查找缓存:

Service Worker -> Memory Cache -> Disk Cache -> Push Cache

200 from memory cache

表示不向服务器发起请求,从内存缓存获取数据。从内存中获取数据,读取速度较快,但关闭tab后,资源随之被销毁。一般来说,内存缓存存储较小的文件

200 from disk cache

表示不向服务器发起请求,从磁盘缓存获取数据。与内存相比,硬盘的读取速度相对较慢,但硬盘缓存持续的时间更长,关闭tab之后,缓存的资源仍然存在。同时,磁盘的容量较大,一般用于存储大文件