天天看点

http协议之客户端缓存cache-control

作者:宁静知行者
http协议之客户端缓存cache-control

cache-control 是通用消息头字段,被用于http协议中请求与响应中,通过指定指令来实现缓存机制。

cache-control 有以下的属性,多个可以以逗号分隔

名称 说明
max-age=<seconds> 设置客户端缓存的最大周期,超过则被认为是过期
s-maxage=<seconds> 覆盖 max-age,但只适用于代理服务器
public 表明响应可以被任何对象缓存,包括代码服务器、客户端
private 表明响应只能被单个用户缓存,不能作为共享缓存
no-cache 强制要求缓存把请求提交给原始服务器进行验证(协商缓存验证)
no-store 缓存不应存储有关客户端请求或是服务器响应的任何内容,即不使用任何缓存

max-age 与 s-maxage

cache-control: max-age=N, N 即是缓存的秒数,从第一次请求资源的时候开始计算,之后N秒内,再进行资源请求,则会从本地磁盘或是内存中读取,不会再与服务器进行任务的交互。

cache-control: s-maxage=N, 是设置代理服务器可以缓存的时长,单位为秒

no-cache 与 no-store 的使用

no-cache 并不是说不缓存,而是强制进行协商缓存,如果某一个资源 cache-control 中有设置 no-cache, 那么该资源会跳过强制缓存的校验,而是会与服务端进行协商缓存,而no-store是禁止所有的缓存策略

public 与 private

这两个参数是为了指定可以缓存该对象的用户,请求资源的流程可以是以下两种

http协议之客户端缓存cache-control
http协议之客户端缓存cache-control

如果指定为public,则以上两种都可以进行缓存。

如果是指定为private,则代理服务器是不允许进行缓存的。

缓存

基于expires

在http/1.0 使用 Expires 字段来标识

HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 1024
Date: Tue, 22 Feb 2023 22:22:22 GMT
Last-Modified: Tue, 22 Feb 2023 22:00:00 GMT
Cache-Control: max-age=3600           

但因为时间格式比较难解析,也有可能因为客户端与服务端的时间不同,而引发一些问题,所以在 http/1.1中使用 cache-control: max-age 用于指定经过的时间.

如上面的响应是从2023年2月22日 22:22:22 开始,往后1 小时,这个资源都是可以从本地缓存中获取(强制缓存),而过时(stale)的资源也不会立即丢弃,会先请求一次进行验证,会带上 If-Modified-Since,而这个值就是第一次请求时返回的 Last-Modified (协商缓存)

GET /index.html HTTP/1.1
Host: example.com
Accept: text/html
If-Modified-Since: Tue, 22 Feb 2023 22:00:00 GMT
           

如果没有变化则是响应 304 Not Modified.

HTTP/1.1 304 Not Modified
Content-Type: text/html
Date: Tue, 22 Feb 2023 23:22:22 GMT
Last-Modified: Tue, 22 Feb 2023 22:00:00 GMT
Cache-Control: max-age=3600           

基于ETag

因为使用 Last-Modified 方式,会存在时间解析,服务器时间难同步的问题,ETag 方式被提出来,通过生成主体内容的哈希值或是版本号。

如下的响应:

HTTP/1.1 200 OK
Content-Type: text/html
Content-Length: 1024
Date: Tue, 22 Feb 2023 22:22:22 GMT
ETag: "xxtttee"
Cache-Control: max-age=3600           

在一小时内,这个缓存是有效的,可以访问本地的缓存数据(强制缓存),而如果本地缓存失效(stale),则再次请求时会增加请求头 If-None-Match: "" (协商缓存),而这个值为上次请求时返回的 ETag,服务端在接收到这个请求后,会比对这个ETag的值,如果相同,则会返回 状态码为 304 ,客户端可以继续使用这个缓存在 max-age的时间范围内,如果ETag有变化,则返回状态码200,并将内容也一同返回。

GET /index.html HTTP/1.1
Host: example.com
Accept: text/html
If-None-Match: "xxtttee"           
HTTP/1.1 304 Not Modified           

如果服务端未返回相应的字段,则浏览器会使用启发式的算法,通过响应头中的Date 减去 Last-Modified 值的 %10 作为缓存时间

总结下流程,如下:

http协议之客户端缓存cache-control

请求头中的cache-control

当在请求头中设置 cache-control 是指示当前请求应该走什么样的缓存策略

cache-control: max-age=0 表示当前的请求按协商缓存的规则走,一定会发出真实的请求

cache-control: no-cache ,一般会附带 Pragma: no-cache,是为了兼容 http/1.0, 表示这次请求不会读缓存资源,即使缓存没有过期,也不会携带 协商缓存相关的请求头,所以也不会有304的状态出现。

在请求头中的cache-control 也只能使用上面的两种值。

总结

  1. 对于频繁变动的资源可以设置 cache-control: no-cache 进行协商
  2. 不常变动的资源可以设置 cache-control: max-age= 比较大值,如 32536000(一年)

继续阅读