no-cache 和 must-revalidate 之间的区别

Posted

技术标签:

【中文标题】no-cache 和 must-revalidate 之间的区别【英文标题】:Difference between no-cache and must-revalidate 【发布时间】:2013-08-11 12:21:56 【问题描述】:

来自 RFC 2616

http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9.1

无缓存

如果 no-cache 指令未指定字段名,则缓存 不得使用响应来满足后续请求 与源服务器成功重新验证。这允许原点 服务器以防止缓存,即使是已配置为的缓存 对客户端请求返回陈旧的响应。

因此它指示代理重新验证所有响应。

对比一下

必须重新验证

当 must-revalidate 指令出现在收到的响应中时 通过缓存,该缓存在它变得陈旧后不得使用该条目 响应后续请求,而无需先重新验证它 源服务器

因此它指示代理重新验证陈旧响应。

特别是关于no-cache,用户代理实际上是这样对待这个指令的吗?

如果有must-revalidatemax-age,那么no-cache 有什么意义?

看到这条评论:

http://palpapers.plynt.com/issues/2008Jul/cache-control-attributes/

无缓存

虽然这个指令听起来像是在指示浏览器不要 缓存页面,有一个细微的差别。 “无缓存”指令, 根据 RFC,告诉浏览器它应该重新验证 服务器在从缓存中提供页面之前。重新验证是一个 让应用程序节省带宽的巧妙技术。如果 浏览器缓存的页面没有改变,服务器只是发出信号 到浏览器,页面从缓存中显示。因此, 浏览器(至少在理论上)将页面存储在其缓存中,但是 仅在与服务器重新验证后才显示。在实践中,IE 并且 Firefox 已经开始将 no-cache 指令视为 指示浏览器甚至不缓存页面。我们开始观察 这种行为大约在一年前。我们怀疑这种变化是 该指令的广泛(和不正确)使用提示 防止缓存。

有人对此有更官方的说法吗?

更新

服务器应该使用 must-revalidate 指令当且仅当未能验证对表示的请求可能导致不正确的操作,例如静默未执行的金融交易。

这是我直到现在才想到的事情。 RFC 说不要轻易使用 must-revalidate。问题是,对于 Web 服务,您必须对未知的客户端应用程序采取负面看法并假设最坏的情况。任何陈旧的资源都有可能导致问题。

我刚刚考虑过的其他事情,没有 Last-Modified 或 ETags,浏览器只能再次获取整个资源。但是,使用 ETags,我观察到 Chrome 至少似乎对每个请求都重新验证。这使得这两个指令没有实际意义,或者至少命名不佳,因为它们无法正确重新验证,除非请求还包含其他导致“始终重新验证”的标头。

我只是想让最后一点更清楚。通过仅设置 must-revalidate 但不包括 ETag 或 Last-Modified,代理只能再次获取内容,因为它没有任何内容可发送到服务器进行比较。

但是,我的经验测试表明,当响应中包含 ETag 或修改后的标头数据时,无论must-revalidate 标头是否存在,代理总是会重新验证。

所以must-revalidate 的重点是在它过时时强制“绕过缓存”,这只能在您设置生命周期/年龄时发生,因此如果must-revalidate 设置在没有年龄的响应上或其他标头,它实际上等效于no-cache,因为响应将立即被视为陈旧。

-- 所以我要最终标记吉利的答案!

【问题讨论】:

所以理论上区别是 validate-alwaysvalidate-if-stale,而实际上 no-cache 被某些浏览器视为您引用的评论说 never-validate ...因此您应该根据实际想要实现的缓存行为来选择使用哪一个 ... 请阅读greenbytes.de/tech/webdav/…,看看这是否为您澄清了事情。 What's the difference between Cache-Control: max-age=0 and no-cache?的可能重复 检查此决策树以获取答案 ***.com/a/49925190/3748498 【参考方案1】:

我相信must-revalidate 的意思是:

一旦缓存过期,拒绝向用户返回陈旧的响应 即使他们说陈旧的响应是可以接受的。

no-cache 暗示:

must-revalidate 加上响应立即变得陈旧的事实。

如果响应可缓存 10 秒,则 must-revalidate 在 10 秒后启动,而 no-cache 意味着 must-revalidate 在 0 秒后。

至少,这是我的解释。

【讨论】:

这就是我现在看到的。有趣的部分是我的最后一段,没有 ETag 或 Last-Modified,代理没有任何东西可用于验证它在缓存中的内容,并且必须再次下载整个有效负载。因此,当 RFC 说“重新验证”时,这可能意味着重新获取。 这也意味着max-age=0, must-revalidateno-cache是相同的 @Anshul,起初我认为你是对的,'max-age=0,must-revalidate 和 no-cache 是相同的',但请参阅 Jeffrey Fox 的回答,这似乎表明这不太正确. @Anshul 否,must-revalidateno-cache 对新鲜响应有不同的含义:如果缓存的响应是新鲜的(即响应尚未过期),must-revalidate 将做代理立即提供它而不用服务器重新验证,而使用no-cache 代理必须重新验证缓存的响应,无论新鲜度如何。资料来源:“HTTP - The Definitive Guide”,第 182-183 页。 @MatthiasBraun 啊,我可以看到混乱的根源。可能我应该写 no-cachemax-age=0, must-revalidate 是相同的【参考方案2】:

max-age=0, must-revalidateno-cache 并不完全相同。使用must-revalidate,如果服务器没有响应重新验证请求,浏览器/代理应该返回 504 错误。使用no-cache,它只会显示缓存的内容,这可能是用户的首选(有一些陈旧的东西总比什么都没有好)。这就是must-revalidate 仅用于关键事务的原因。

【讨论】:

不确定您对no-cache 的解释。来自RFC 7234 的“no-cache”响应指令表明,在没有在源服务器上成功验证的情况下,不得使用响应来满足后续请求。这允许源服务器阻止缓存使用它来满足请求而不联系它,即使是通过已配置为发送陈旧响应的缓存。这听起来类似于must-revalidate的限制 Jeffrey 是否有证据表明实现的行为符合他的描述? 我认为这个答案对于代理/磅服务器是正确的。但实际上,在这种情况下,浏览器不会返回 504。 所以must-validate 表示must-refresh developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control 直接声明“no-cachemax-age=0, must-revalidate 表示相同的意思。”【参考方案3】:

根据 Jeffrey Fox 对no-cache 的解释,我在 chrome 52.0.2743.116 m 下测试,结果显示no-cachemust-revalidate 行为相同,它们都会不会当服务器无法访问时使用本地缓存,并且,当服务器无法访问时,它们都会在点击浏览器的后退/前进按钮时使用缓存。 如上所述,我认为max-age=0, must-revalidateno-cache 相同,至少在实现上是这样。

【讨论】:

当服务器可用于重新验证时,Chrome 是否会使用本地缓存? (即“If-Modified-Since”)。在这两种情况下?【参考方案4】:

我觉得max-age=0, must-revalidateno-cache是有区别的:

must-revalidate 情况下,允许客户端发送If-Modified-Since 请求并在返回304 Not Modified 时从缓存中提供响应。

no-cache的情况下,客户端不能缓存响应,所以不应该使用If-Modified-Since

【讨论】:

但是no-cache不代表no-store——有了no-cache,资源仍然可以缓存在客户端;是否必须在使用前重新验证? 您将no-cacheno-store 混为一谈。 no-cache 表示资源必须重新验证重新验证包括使用条件请求的选项,例如If-None-MatchIf-Modified-Since @JulesRandolph:你可能是对的。你有任何测试/演示吗?关于这个 q 的所有相互矛盾的无证据断言都令人沮丧。即使是接受的答案也只是说“至少,这是我的解释”。如果有时间,我可能会设置一个测试平台并将其发布在这里。【参考方案5】:

同意@Jeffrey Fox 的部分回答:

max-age=0,must-revalidate 和 no-cache 并不完全相同。

不同意这部分:

如果没有缓存,它只会显示缓存的内容,这可能是用户更喜欢的(有一些陈旧的东西总比什么都没有好)。

cache-control: no-cache 重新验证失败时,实现应该做什么只是没有在 RFC 文档中指定。这完全取决于实施。他们可能会抛出像 cache-control: must-revalidate 这样的 504 错误,或者只是从缓存中提供一个过时的副本。

【讨论】:

以上是关于no-cache 和 must-revalidate 之间的区别的主要内容,如果未能解决你的问题,请参考以下文章

http协议缓存小结

docker build --no-cache 会构建不同的层吗?

HTML meta pragma no-cache 页面缓存

Pragma: no-cache

web性能优化之:no-cache与must-revalidate深入探究

web 性能优化之:no-cache 与 must-revalidate 深入探究