将 Cache-Control: max-age 与 ETag 一起使用时会发生啥?

Posted

技术标签:

【中文标题】将 Cache-Control: max-age 与 ETag 一起使用时会发生啥?【英文标题】:What happens when you use Cache-Control: max-age with ETags?将 Cache-Control: max-age 与 ETag 一起使用时会发生什么? 【发布时间】:2021-09-06 13:50:55 【问题描述】:

有几个类似的问题,但我发现没有一个是明确或明确的。

这是我想要的行为:

只要网络可用,浏览器必须检查是否有新版本 如果没有新版本,浏览器可以使用缓存的版本 缓存版本在 X 天后过期

我想我可以用 Cache-Control: max-age 和 ETags 做到这一点。但是,我找不到 max-age 是否应该是 0 或者内容应该缓存多长时间。

例如如果我用 ETag 做Cache-Control: max-age=86400(1 天),会不会:

    每次都向服务器发出请求,但如果 ETag 没有更改,服务器只会返回 304。 1天后,丢弃缓存的版本,从服务器重新获取(应该与丢弃的版本相同)。

    一天不发出任何服务器请求。然后,1天后,服务器仍然可以返回304。缓存的版本可以无限期保留。

我希望浏览器在 X 天后重新获取,因为万一出现错误,我不希望用户被损坏的缓存版本卡住。

【问题讨论】:

【参考方案1】:

这是我想要的行为:

只要网络可用,浏览器必须检查是否有新版本 如果没有新版本,浏览器可以使用缓存的版本

这是一个常见的用例,可以通过使用Cache-Control: no-cache(或max-age=0, must-revalidate)并提供ETagLast-Modified 标头来完成。

缓存版本在 X 天后过期

这是不可能的。它不是 HTTP 缓存设计的一部分,因为它没有用例。

我希望浏览器在 X 天后重新获取,因为万一出现错误,我不希望用户被损坏的缓存版本卡住。

如果浏览器每次都检查新版本,用户怎么会被“损坏”的缓存版本卡住?

如果我用 ETag 做Cache-Control: max-age=86400(1 天),会不会:

    每次都向服务器发出请求,但如果 ETag 没有更改,服务器只会返回 304。 1天后,丢弃缓存的版本,从服务器重新获取(应该与丢弃的版本相同)。

    一天不发出任何服务器请求。然后,1天后,服务器仍然可以返回304。缓存的版本可以无限期保留。

数字 2。max-age 告诉浏览器它可以在多长时间内认为资源是新鲜的,这意味着可以使用缓存的版本而无需与服务器检查。当该时间到期时,资源将被视为陈旧,并且必须发出新请求。如果缓存的资源具有ETagLast Modified 标头,则该请求可以是有条件的,以允许服务器避免在响应中发送整个资源。

【讨论】:

一个用例可能是错误生成 ETag 的错误,因此即使内容更改,服务器也总是返回 304。之前我有一个错误,用户被陈旧的脚本卡住了很长时间,忘记了发生了什么 @LeoJiang:在那种情况下可能发生的事情,并且有点常见的是max-age被设置了很长时间。这是一个真正的问题,因为此时服务器无法强制浏览器请求新版本。相反,在不正确的ETags 的情况下,服务器处于控制之中,一旦修复了错误,下一个请求就会正常工作。所以这真的不是问题。

以上是关于将 Cache-Control: max-age 与 ETag 一起使用时会发生啥?的主要内容,如果未能解决你的问题,请参考以下文章

CloudFront“age”标头对“cache-control: private; max-age=3600”的影响

max-age, no-Cache,must-revalidate on Cache-Control Header,这里优先考虑哪个?

如何在 Rails 环境中使用 Cache-Control: max-age Header 来控制 Varnish 和浏览器?

爱创课堂每日一题第二十三天- Expires和Cache-Control?

HTTP Header之Cache-Control

Why use Cache-Control header in request?