客户端缓存的副本可能会与服务器上的文档不一致,因为这些文档可能会随时间发生变化。所以缓存的数据与服务器数据保持一致是重要的,HTTP有一些机制来做这件事。
1 文档过期
使用 Cache-Control
或 Expires
可以给文档添加一个过期时间,缓存过期之前,客户端可以直接使用缓存,而无需和服务端联系。缓存一旦过期,就需要询问服务端文档是否修改过,如果修改过,则需要获取一份新的副本。
2 过期日期和使用期
Cache-Control
使用相对时间;Expires
使用绝对时间,这依赖于计算机时钟的正确设置。
3 服务器再验证
验证时如果文档内容没有变化,那么只需要用新的 response header 更新过期时间即可。
4 用条件方法进行再验证
HTTP条件方法可以高效地实现再验证,这种方式将新鲜度检测和获取对象结合成了单个请求。
If-Modified-Since: <date>
: 如果在指定日期之后文档修改过,就执行请求的方法
If-None-Match: <tags>
: 如果已缓存的 ETag 与服务器文档中的 ETag 不同,就执行请求的方法
5 If-Modified-Since: Date
再验证
如果文档没有变化,返回 304 响应报文。
If-Modified-Since
可以和 Last-Modified
配合,验证时使用 Last-Modified
给出的日期。
6 If-None-Match
: Entity Tag 再验证
ETag
是版本标识符。有些场景只使用最后修改日期进行再验证是不够的,比如修改的内容并不重要,不需要缓存更新。
当发布者对文档修改时,可以修改文档的ETag
来说明这个新的版本。
7 强弱验证器
用 w/
标记弱验证器,ETag: W/"v2.6"
8 何时用 Entity Tags 和 Last-Modified Dates
如果服务器只提供了Last-Modified
值,那就用If-Modified-Since
验证;
如果服务器提供了ETag
值,就用ETag
验证;
如果两者都提供了,只有两者都满足时才能返回 304 Not Modified
总结:
服务器给出Cache-Control
或 Expires
响应头,表示文档过期时间。过期之前浏览器直接使用缓存的内容,而不重新发出请求。
过期之后根据服务器给的Last-Modified
或 ETag
相应头,客户端使用 If-Modified-Since: <date>
或 If-None-Match: <tags>
发出请求,如果文档未发生变化,返回 304 Not Modified,否则返回新的文档。
参考资料:
《HTTP权威指南》