标头 Cache-Control: max-age=0
意味着内容被立即视为过时(并且必须重新获取),这实际上与 Cache-Control: no-cache
相同。
我有同样的问题,并在我的搜索中找到了一些信息(您的问题作为结果之一出现)。这是我确定的...
Cache-Control
标头有两个方面。一方面是网络服务器(又名“源服务器”)可以发送它的地方。另一边是浏览器可以发送的地方(又名“用户代理”)。
当由源服务器发送时
我相信 max-age=0
只是告诉缓存(和用户代理)响应从一开始就过时,因此他们应该在使用缓存之前重新验证响应(例如使用 If-Not-Modified
标头)副本,而 no-cache
告诉他们在使用缓存副本之前必须重新验证。从 14.9.1 What is Cacheable:
no-cache ...在没有成功重新验证原始服务器的情况下,缓存不得使用响应来满足后续请求。这允许源服务器阻止缓存,即使缓存已配置为向客户端请求返回陈旧响应。
换句话说,缓存有时可能会选择使用过时的响应(尽管我相信他们必须添加一个 Warning
标头),但 no-cache
表示无论如何都不允许使用过时的响应。当棒球统计数据在页面中生成时,您可能希望 SHOULD-revalidate 行为,但在生成响应时您希望 MUST-revalidate 行为到电子商务购买。
尽管您说 no-cache
不应该阻止存储时您的评论是正确的,但实际上可能是使用 no-cache
时的另一个区别。我遇到了一个页面,Cache Control Directives Demystified,上面写着(我不能保证它的正确性):
实际上,IE 和 Firefox 已经开始将 no-cache 指令视为指示浏览器甚至不缓存页面。我们大约在一年前开始观察这种行为。我们怀疑此更改是由广泛(且不正确)使用此指令来防止缓存引起的。 ...请注意,最近,“cache-control: no-cache”也开始表现得像“no-store”指令。
顺便说一句,在我看来,Cache-Control: max-age=0, must-revalidate
基本上应该与 Cache-Control: no-cache
表示相同的意思。所以也许这是一种获得 no-cache
的 MUST-revalidate 行为的方法,同时避免 no-cache
明显迁移到与 no-store
做同样的事情(即没有任何缓存)?
当由用户代理发送时
我相信 shahkalpesh's answer 适用于用户代理端。您还可以查看 13.2.6 Disambiguating Multiple Responses。
如果用户代理发送带有 Cache-Control: max-age=0
的请求(又名“端到端重新验证”),那么沿途的每个缓存都将重新验证其缓存条目(例如,使用 If-Not-Modified
标头)一直到源服务器。如果回复为 304(未修改),则可以使用缓存的实体。
另一方面,使用 Cache-Control: no-cache
(又名“端到端重新加载”)发送请求不会重新验证,并且服务器不得在响应时使用缓存副本。
最大年龄=0
这相当于点击刷新,意思是,除非我已经有最新的副本,否则给我最新的副本。
无缓存
这是在单击刷新时按住 Shift,这意味着无论如何都重做所有内容。
no-store
现在是老问题,但如果其他人像我一样通过搜索遇到这个问题,IE9 似乎将利用它来配置使用后退和前进按钮时资源的行为。当使用 max-age=0 时,浏览器在后退/前进时查看资源时将使用最新版本。如果使用 no-cache,资源将被重新获取。
有关 IE9 缓存的更多详细信息,请参阅此 msdn caching blog post。
在我最近对 IE8 和 Firefox 3.5 的测试中,似乎两者都符合 RFC。但是,它们对原始服务器的“友好性”有所不同。 IE8 以与 max-age=0,must-revalidate
相同的语义处理 no-cache
响应。然而,Firefox 3.5 似乎将 no-cache
视为等同于 no-store
,这会降低性能和带宽使用率。
默认情况下,Squid Cache 似乎从不存储带有 no-cache
标头的任何内容,就像 Firefox 一样。
我的建议是为您希望检查每个请求的新鲜度的非敏感资源设置 public,max-age=0
,但仍允许缓存的性能和带宽优势。对于具有相同考虑的每用户项目,请使用 private,max-age=0
。
我会完全避免使用 no-cache
,因为它似乎已被某些浏览器和流行的缓存混为一谈,使其功能等同于 no-store
。
此外,不要模仿 Akamai 和 Limelight。虽然他们基本上将大规模缓存阵列作为他们的主要业务,并且应该是专家,但他们实际上对从他们的网络下载更多数据有既得利益。 Google 也可能不是模拟的好选择。他们似乎根据资源随机使用 max-age=0
或 no-cache
。
private,max-age=0
。
max-age When an intermediate cache is forced, by means of a max-age=0 directive, to revalidate its own cache entry, and the client has supplied its own validator in the request, the supplied validator might differ from the validator currently stored with the cache entry. In this case, the cache MAY use either validator in making its own request without affecting semantic transparency. However, the choice of validator might affect performance. The best approach is for the intermediate cache to use its own validator when making its request. If the server replies with 304 (Not Modified), then the cache can return its now validated copy to the client with a 200 (OK) response. If the server replies with a new entity and cache validator, however, the intermediate cache can compare the returned validator with the one provided in the client's request, using the strong comparison function. If the client's validator is equal to the origin server's, then the intermediate cache simply returns 304 (Not Modified). Otherwise, it returns the new entity with a 200 (OK) response. If a request includes the no-cache directive, it SHOULD NOT include min-fresh, max-stale, or max-age.
礼貌:http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9.4
不要接受这个作为答案 - 我将不得不阅读它以了解它的真正用法:)
我几乎不是缓存专家,但 Mark Nottingham 是。这是他的caching docs。他在参考资料部分也有很好的链接。
根据我对这些文档的阅读,看起来 max-age=0
可以允许缓存向“同时”进入的请求发送缓存响应,其中“同一时间”意味着它们足够接近,它们看起来与缓存同时发生,但 no-cache
不会。
顺便说一句,值得注意的是,一些移动设备,尤其是 iPhone/iPad 等 Apple 产品完全忽略了诸如 no-cache、no-store、Expires: 0 之类的标头,或者您可能试图强制它们不重复使用过期的任何其他标头表单页面。
这让我们头疼不已,因为我们试图让用户的 iPad 说,在他们通过表单过程到达的页面上睡着了,比如步骤 2 of 3,然后设备完全忽略了商店/缓存指令,据我所知,它只是从页面的最后状态获取页面的虚拟快照,也就是说,忽略明确告知的内容,不仅如此,获取不应存储的页面, 并在没有实际检查的情况下存储它,这会导致各种奇怪的 Session 问题等等。
我只是添加这个以防有人出现并且无法弄清楚为什么他们会遇到特别是 iphone 和 ipad 的会话错误,这似乎是该领域迄今为止最严重的违规者。
我已经对这个问题进行了相当广泛的调试器测试,这是我的结论,设备完全忽略了这些指令。
即使在常规使用中,我发现某些手机也完全无法通过例如 Expires: 0 检查新版本,然后检查最后修改日期以确定是否应该获得新版本。
它根本不会发生,所以我被迫做的是向我需要强制更新的 css/js 文件添加查询字符串,这会欺骗愚蠢的移动设备认为它是它没有的文件,例如:我的.css?v=1,然后 v=2 用于 css/js 更新。这在很大程度上有效。
顺便说一句,用户浏览器如果保留其默认设置,截至 2016 年,正如我不断发现的那样(我们对我们的网站进行了大量更改和更新)也无法检查此类文件的最后修改日期,但查询string 方法解决了这个问题。这是我注意到的客户和办公室人员,他们倾向于在浏览器上使用基本的普通用户默认设置,并且没有意识到 css/js 等的缓存问题,几乎总是无法获得新的 css/js 更改,这意味着他们的浏览器的默认设置,主要是 MSIE / Firefox,没有按照他们被告知的去做,他们忽略更改并忽略最后修改日期并且不验证,即使明确设置了 Expires: 0。
这是一个很好的线程,有很多很好的技术信息,但同样重要的是要注意对这些东西的支持在特别是移动设备中有多糟糕。每隔几个月,我就必须添加更多的保护层,以防止他们无法遵循他们收到的标题命令,或者正确地解释这些命令。
(令人惊讶的是)没有提到的一件事是,请求可以使用 max-stale
指令明确指示它将接受陈旧数据。在这种情况下,如果服务器以 max-age=0
响应,缓存将只考虑响应陈旧,并且可以自由地使用它来满足客户端的请求 [它要求潜在的陈旧数据]。相比之下,如果服务器发送的 no-cache
确实胜过客户端(使用 max-stale
)对陈旧数据的任何请求,因为缓存必须重新验证。
这直接在 MDN docs about cache control 中回答:
大多数 HTTP/1.0 缓存不支持 no-cache 指令,因此历史上使用 max-age=0 作为解决方法。但是只有 max-age=0 可能会导致在缓存与源服务器断开连接时重用陈旧的响应。 must-revalidate 解决了这个问题。这就是为什么下面的示例等效于无缓存的原因。 Cache-Control: max-age=0, must-revalidate 但是现在,您可以简单地使用 no-cache 代替。
而且在 MDN docs about cache validation 中:
人们常说 max-age=0 和 must-revalidate 的组合与 no-cache 的含义相同。 Cache-Control: max-age=0, must-revalidate max-age=0 表示响应立即过时,must-revalidate 表示一旦过时,不得在没有重新验证的情况下重用它——所以结合起来,语义似乎与无缓存相同。然而,max-age=0 的使用是 HTTP/1.1 之前的许多实现无法处理 no-cache 指令这一事实的残余——因此为了解决这个限制,max-age=0 被用作一种解决方法。但是现在符合 HTTP/1.1 的服务器已经广泛部署,没有理由使用 max-age=0-and-must-revalidate 组合——您应该只使用 no-cache。
must-revalidate
并不意味着与no-cache
或no-store
相同。后者完全绕过缓存,但前者只是说必须始终检查缓存的新鲜度,但如果它仍然是最新的,则可以使用它,从而节省带宽。后者始终强制进行完整的端到端下载,占用不必要的带宽并延迟响应。no-cache
不“完全绕过缓存”或“始终强制进行完整的端到端下载”,至少不是在所有浏览器中。 The specification 仅表示浏览器必须验证缓存。