HTTP缓存相关的回顾

June 6, 2015

282

最近,对HTTP缓存一些相关知识有些遗忘,对Cache-Control、Expires、If-Modified-Since等首部有些混淆等,重新查阅了相关知识并记录如下。

对一条HTTP GET报文的缓存处理主要为一下7个步骤:

  1. 接收——缓存从网络中读取抵达的请求报文。
  2. 解析——缓存对报文进行解析,提取出URL和各种首部。
  3. 查询——缓存查看是否有本地副本可用,如果没有,就获取一份副本并将其保存在本地。
  4. 新鲜度检测——缓存查看已缓存副本是否足够新鲜,如果不是,就询问服务器是否有任何更新。
  5. 创建响应——缓存会用新的首部和已缓存的主体来构建一条响应报文。
  6. 发送——缓存通过网络将响应发送给客户端。
  7. 日志——缓存可选地创建一个日志文件条目来描述这个事务。

【文档过期】通过Cache-Control首部和Expires首部,HTTP让原始服务器向每个文档附加了一个“过期日期”。在缓存文档过期之前,缓存可以以任何频率使用这些副本,而无须与服务器联系。Expires首部和Cache-Control:max-age首部所做的事情本质上是一样的,那么为啥HTTP会有这两个头部?

Expires首部是HTTP/1.0定义的字段,指定的是一个绝对的过期日期。而Cache-Control是HTTP/1.1定义的字段,max-age值定义了文档的最大使用值,是相对时间。所以,我们更倾向于使用比较新的Cache-Control首部,绝对时间需要依赖于计算机时钟的正确设置。当同时存在Expires和Cache-Control:max-age字段时,Cache-Control:max-age字段会覆盖Expires字段。同时存在这两个字段还有一个好处,就是可以兼容HTTP/1.0。

【服务器再验证】仅仅已缓存过期了并不意味着它和原始服务器上目前处于活跃状态的文档有实际的区别,这时候缓存需要询问原始服务器文档是否发生了改变。

  1. 如果再验证显示内容发生了改变,缓存会获取一份新的文档副本,并将其存储在旧文档的位置上,然后将文档发送给客户端。
  2. 如果再验证显示内容没有发生变化,缓存只需要获取新的首部,包括一个新的过期日期,并对缓存中的首部进行更新就行了。

HTTP条件方法可以高效地实现再验证。HTTP定义了五个条件请求首部,包括If-Modified-Since、If-None-Match、If-Unmodified-Since、If-Range和If-Match。其中,对缓存再验证来说最有用的2个首部是If-Modified-Since和If-None-Match。

1. If-Modified-Since:Date再验证

如果自指定日期后,文档被修改了,If-Modified-Since条件就为真,GET就会执行成功。携带新首部的新文档会被返回给缓存,新首部除了其他信息之外,还包含了一个新的过期日期。

如果自指定日期后,文档没被修改过,条件就为假,会向客户端返回一个小的304 Not Modified响应报文,不会返回文档的主体,只会返回那些需要在源端更新的首部。

If-Modified-Since首部可以和Last-Modified服务器响应首部配合工作。原始服务器会将最后的修改日期附加到所提供的文档上去。If-Modified-Since: <cached last-modified date>

2. If-None-Match: 实体标签再验证

有些文档可能被被周期性的重写、有些文档可能被修改了但所做修改不重要等等这类情况下,使用最后修改日期进行再验证是不够的,这时候HTTP允许用户对被称为实体标签ETag的“版本标识符”进行比较。ETag是附加到文档上的任意标签,可能包含了文档的序列号或版本名,或者是文档内容的校验和及其他指纹信息。当发布者对文档进行修改时,可以修改文档的实体标签来说明这个新的版本。

实体标签和最近修改日期都是缓存验证器,那么什么时候应该使用实体标签和最近修改日期呢?

如果服务器回送了一个实体标签,HTTP/1.1客户端就必须使用实体标签验证器。如果只返回了一个Last-Modified值,客户端就可以使用If-Modified-Since验证。如果实体标签和最后修改日期都提供了,客户端就应该使用这两种再验证方案,这样HTTP/1.0和HTTP/1.1缓存就都可以正确响应了。如果HTTP/1.1缓存或服务器收到的请求既带有If-Modified-Since,又带有ETag条件首部,那么需要这两个条件都满足时,才能返回304 Not Modified响应。

【缓存控制】服务器可以通过HTTP定义的几种方式来指定文档过期之前可以将其缓存多长时间。

  • Cache-Control: no-store 缓存应该尽快从存储器中删除文档的所有痕迹。
  • Cache-Control: no-cache 响应实际上是可以存储到本地缓存区中的,只是在与服务器进行新鲜度再验证之前,缓存不能将其提供给客户端使用。
  • Cache-Control: must-revalidate 在事先没有跟原始服务器进行再校验的情况下,不能提供这个对象的陈旧副本。缓存仍能可以随时提供新鲜的副本。
  • Cache-Control: max-age 表示从服务器将文档传来之时至最大秒数,可以认为文档处于新鲜状态。
  • Expires: 指定实际的过期日期。
  • 试探性过期: 不添加过期信息,让缓存确定自己的过期日期。

HTTP 」相关文章

Wen's Blog

文章归档 » 文章标签 » 博主:吴文伟,Web开发爱好者,专注于前端开发,该博客用于记录和分享平时遇到的一些问题以及知识。

订阅

联系方式

链接