在最大缓存时间到期后检查HTTP资源是否已更改

时间:2015-09-03 18:06:24

标签: http caching browser-cache http-caching

我正在尝试为网站上的静态资源制定新的缓存策略。一个常见的问题是,无论何时更新javascript,CSS等,许多用户都会使用旧版本,因为目前文件响应中不包含缓存特定的HTTP头。

例如,当javascript更新链接到服务器端更新,以及新服务器响应中陈旧的javascript阻塞时,这就成了一个严重的问题。

使用cache-control: max-age=0, no-cache完全消除浏览器缓存似乎有点矫枉过正,因为我仍然希望通过暂时缓存浏览器来减轻服务器的压力。因此,将缓存策略设置为最多一小时似乎没问题,例如cache-control: max-age=3600, no-cache

我的理解是,如果缓存的副本超过一小时,这将始终获取资源的新副本。我特别想知道是否可以设置HTTP标头或标头组合,这将指示浏览器仅在超过一小时前上次检查时才获取新副本并且如果资源已更改

我只是试图避免浏览器盲目地获取新副本只是因为缓存的资源超过一小时,所以我还想添加资源已被更改的条件。

进一步说明我的要求:

  1. 新用户到达网站并获取script.js
  2. 的新副本
  3. 用户在网站停留45分钟,浏览器始终使用script.js的缓存副本
  4. 用户2小时后返回站点,浏览器询问服务器是否已更改script.js
  5. 如果有,则会获得一份新副本并重复该过程
  6. 如果它没有改变,那么它会在接下来的一小时内使用缓存副本,之后会再次检查
  7. 我误解了什么吗?我问的是它实际上是如何工作的,还是我必须做一些不同的事情?

2 个答案:

答案 0 :(得分:0)

似乎我误解了它是如何工作的,因为Chrome中的某些测试已经在我提到的5个步骤中准确地揭示了我正在寻找的行为。

当max-age到期时,它不会盲目地从服务器获取新副本。它执行GET,如果响应是304(未修改),它将继续使用缓存副本,直到下一个小时到期,此时它会再次检查更改等。

no-cache选项也是错误的。包含它意味着浏览器将始终检查服务器是否每次都对文件进行修改。所以我真正想要的是:

Cache-Control: public, max-age=3600 

答案 1 :(得分:0)

  

我误解了什么吗?我在问它是如何工作的,   或者我必须做些不同的事情吗?

您对各种缓存控制指令的作用以及缓存行为的原因有一些严重的误解。

  

使用缓存控制完全消除浏览器缓存:   max-age = 0,no-cache看起来有点矫枉过正,因为我还是喜欢   通过让浏览器临时缓存来减轻服务器的压力......   no-cache选项也是错误的。包括它意味着浏览器将永远   每次都要检查服务器是否有对文件的修改。

这不是no-cache的意思或它的意图 - 这意味着客户端绝不能使用缓存副本来满足后续请求而没有成功重新验证 - 它不会也从未意味着“不要缓存“ - 这就是no-store指令的用途

此外,max-age指令只是缓存计算缓存条目的新鲜度生命周期和到期时间的主要方法。也可以使用Expires标头(减去Date标头的值) - 也可以使用基于当前UTC时间和任何Last-Modified标头值的启发式方法。

真的,如果你的目标是保留资源的缓存副本,只要它有意义 - 同时尽量减少请求和响应,你有很多选择。

  1. EtagEntity Tag)标头 - 由服务器提供,以响应“强”或“弱”形式的请求。它通常是基于所讨论资源的哈希。当客户端重新请求资源时,它可以使用If-None-Match请求标头传递Etag的存储值。如果资源未更改,则服务器将使用304 Not Modified进行响应。

    您可以将Etags视为资源的指纹。它们可用于大规模减少通过网络发送的信息量 - 因为只提供新数据 - 但它们与请求的次数或频率无关。

  2. last-modified标头 - 由服务器提供,以响应HTTPdate格式的请求 - 它告诉客户端上次修改资源的时间。 当客户端重新请求资源时,它可以使用If-Modified-Since请求标头传递最后修改的标头的存储值。如果资源自上次修改以来未发生更改,则服务器将使用304 Not Modified进行响应。

    您可以将最后一次修改视为比Etags更弱的实体检查形式。它以不太稳健的方式解决了同样的问题(带宽/冗余),并且对实际的请求数量没有任何影响。

  3. Revving - 一种使用Expires标头和资源名称(URN)组合的技术。 (见stevesouders blog post

    这里基本上设置了一个远期Expires标头 - 比如说从现在起5年 - 确保静态资源长时间缓存。

    然后,您有两个更新选项 - 通过将版本控制查询字符串附加到请求URL - 例如“/mystyles.css?v=1.1” - 并在资源更改时更新版本号。或者更好 - 对文件名本身进行版本控制,例如“/mystyles.v1.1.css”以便尽可能长时间地缓存每个版本。

    这样不仅可以减少带宽量 - 在重命名之前,您将消除所有检查以查看资源是否已更改。

  4. 我认为这里的要点是,如果生成max-age响应,那么你提到的public304等等没有任何关联控制指令。对于那个使用Etag / If-None-Matchlast-modified / If-Modified-Since或它们的组合(使用If-Modified-Since作为If-None-Match的回退机制)。