上篇分享学院君已经大致介绍 HTTP 缓存的工作机制,今天我们接着讲 HTTP 缓存在 HTTP/1.1 中的实现。
Cache-Control
在 HTTP/1.0 中通过 Expires 首部字段来判断缓存是否过期,但是 Expires 字段值是一个绝对日期,有其局限性,在 HTTP/1.1 中我们统一通过 Cache-Control 字段来控制缓存的有效期及实现细节。可以说 Cache-Control 是 HTTP 缓存相关首部字段中最重要的一个字段,下面我们具体来看如果通过该字段设置 HTTP 缓存。
在 Cache-Control 字段中可以设置多个属性值,不同属性值之间通过逗号分隔,作为一个通用首部字段,请求头和响应头中都可以出现这个字段,并且通过不同的属性值来定义 HTTP 缓存策略。常见的属性及其含义如下所示:
关于缓存有效性检测(或者叫做新鲜度检测、服务器再验证),在 HTTP/1.1 协议中可以通过两对首部字段来实现。
Last-Modified/If-Modified-Since
Last-Modified 字段常用于响应头中,告知客户端资源的最后修改时间,这样,当客户端再次请求该资源时,会在 If-Modified-Since 请求头字段中带上上次请求返回的最后修改时间,服务器收到请求报文后发现请求头包含 If-Modified-Since 字段,则与被请求资源的最后修改时间进行对比。如果资源的最后修改时间大于 If-Modified-Since 字段值,说明资源又被改动过,则返回完整的资源内容,对应响应状态码为 200;如果资源的最后修改时间小于或等于 If-Modified-Since 字段值,说明资源没有做新的修改,则返回状态码 304,告知浏览器使用本地保存的缓存作为响应实体。
Etag/If-None-Match
和上面那对首部字段类似,Etag 用于响应头中,告知客户端资源在服务器的唯一标识(生成规则由服务器指定,每当资源发生修改后 Etag 值会变化),当客户端再次请求该资源时,通过 If-None-Match 字段通知服务器客户段缓存资源数据的唯一标识。服务器收到请求报文后发现请求头包含 If-None-Match 字段,则与被请求资源的唯一标识进行对比,如果不同,说明资源又被改动过,则返回完整的资源内容,对应响应状态码为 200;如果相同,说明资源没有做新的修改,则返回状态码 304,告知浏览器使用本地保存的缓存作为响应实体。
需要指出的是 Etag/If-None-Match 的优先级要高于 Last-Modified/If-Modified-Since,如果同时出现,以前者为准。
综上,缓存有效性检测逻辑流程图如下所示:
如果把范围再扩大到通过 Cache-Control 来定义 HTTP 缓存策略,则对应的流程图如下所示:
最后一步「Add Etag Header」还可以改为「Add Last-Modified Header」。
以上就是 HTTP 缓存的底层工作机制和实现原理,如果你还有什么不明白,欢迎留言与我讨论。