缓存是一种保存资源副本并在下次请求时直接使用该副本的技术.

Web 缓存能够减少延迟与网络阻塞,进而减少显示某个资源所用的时间。借助 HTTP 缓存,Web 站点变得更具有响应性。

缓存技术有: 网关缓存、CDN、方向代理缓存、负载均衡器等部署在服务器端的缓存技术.

HTTP缓存是浏览器和服务器协同工作完成的一种机制.它可以帮助Web应用更开始的响应用户的行为.

而在HTTP缓存中只能存储GET请求的响应,对于其他类型的响应无能为力.

HTTP的缓存策略通过在请求头中做一些设定完成的.

HTTP缓存方式分为强制缓存和协商缓存

强制缓存

强制缓存, 如果浏览器发现请求资源的日期未过期则直接取本地缓存的副本. 不向服务器发起请求.

Expires

Expires 响应头包含日期/时间, 即在此时候之后,响应过期。

无效的日期,比如 0, 代表着过去的日期,即该资源已经过期。

如果在Cache-Control响应头设置了 “max-age” 或者 “s-max-age” 指令,那么 Expires 头会被忽略。

1
2
Expires: <http-date>
Expires: Wed, 21 Oct 2015 07:28:00 GMT

Cache-Control: mx-age/s-max-age

Cahce-Control的配置指令有很多种,和强制缓存相关的指令有 mx-ages-max=age

mx-age

Cache-Control: max-age=<seconds>

设置缓存存储的最大周期,超过这个时间缓存被认为过期(单位秒)。与Expires相反,时间是相对于请求的时间。

s-max-age

s-maxage=<seconds>覆盖max-age或者Expires头,但是仅适用于共享缓存(比如各个代理),私有缓存会忽略它。

协商缓存

协商缓存,浏览器会向服务器发送请求用来验证本地资源是否过期,服务器会校验客户端资源是否过期,如果未过期则返回304,响应不包含body.否则服务器返回200并且响应体包含body.

ETag/If-None-Match

ETagHTTP响应头是资源的特定版本的标识符。如果给定URL中的资源更改,则一定要生成新的Etag值。 因此Etags类似于指纹,也可能被某些服务器用于跟踪。 比较etags能快速确定此资源是否变化,但也可能被跟踪服务器永久存留。

浏览器在第一次请求资源时.服务器会将资源反回,并将ETag=xxxxx一起返回个浏览器,浏览器在第二次请求相同资源时候,在请求头部设定if-None-Match=ETag的值.

服务器会拿资源最新的ETag值和浏览器传的if-None-Match做对比,如果一样则返回304,否则返回最新的资源和最新ETag值.

Last-Modified/If-Modified-Since

The Last-Modified 是一个响应首部,其中包含源头服务器认定的资源做出修改的日期及时间。 它通常被用作一个验证器来判断接收到的或者存储的资源是否彼此一致。由于精确度比 ETag 要低,所以这是一个备用机制。包含有 If-Modified-SinceIf-Unmodified-Since 首部的条件请求会使用这个字段。

If-Modified-Since 是一个条件式请求首部,服务器只在所请求的资源在给定的日期时间之后对内容进行过修改的情况下才会将资源返回,状态码为 200 。如果请求的资源从那时起未经修改,那么返回一个不带有消息主体的 304 响应,而在 Last-Modified 首部中会带有上次修改时间。 不同于 If-Unmodified-Since, If-Modified-Since 只可以用在 GETHEAD 请求中。

当与 If-None-Match 一同出现时,它(**If-Modified-Since**)会被忽略掉,除非服务器不支持 If-None-Match

缓存策略

除了/定缓存是否过期方式外, 还可以设定缓存的策略

Cache-Control

Cache-Control 通用消息头字段,被用于在http请求和响应中,通过指定指令来实现缓存机制。缓存指令是单向的,这意味着在请求中设置的指令,不一定被包含在响应中。

指令不区分大小写,并且具有可选参数,可以用令牌或者带引号的字符串语法。多个指令以逗号分隔。

1
2
3
4
5
6
max-age:用来设置资源(representations)可以被缓存多长时间,单位为秒;
s-maxage:和max-age是一样的,不过它只针对代理服务器缓存而言;
public:指示响应可被任何缓存区缓存;
private:只能针对个人用户,而不能被代理服务器缓存;
no-cache:强制客户端直接向服务器发送请求,也就是说每次请求都必须向服务器发送。服务器接收到 请求,然后判断资源是否变更,是则返回新内容,否则返回304,未变更。这个很容易让人产生误解,使人误 以为是响应不被缓存。实际上Cache-Control:no-cache是会被缓存的,只不过每次在向客户端(浏览器)提供响应数据时,缓存都要向服务器评估缓存响应的有效性。
no-store:禁止一切缓存(这个才是响应不被缓存的意思)。

Vary

Vary是一个HTTP响应头部信息,它决定了对于未来的一个请求头,应该用一个缓存的回复(response)还是向源服务器请求一个新的回复。它被服务器用来表明在 content negotiation algorithm(内容协商算法)中选择一个资源代表的时候应该使用哪些头部信息(headers).

1
2
3
4
5
Vary: *
Vary: <header-name>, <header-name>, ...

Vary: User-Agent
哪种情况下使用 Vary: 对于User-Agent 头部信息,例如你提供给移动端的内容是不同的,可用防止你客户端误使用了用于桌面端的缓存。

参考

https://juejin.im/post/5ccfccaff265da03ab233bf5