即使使用缓存控制,来自云端的 RefreshHit:max-age=0, no-store
Posted
技术标签:
【中文标题】即使使用缓存控制,来自云端的 RefreshHit:max-age=0, no-store【英文标题】:RefreshHit from cloudfront even with cache-control: max-age=0, no-store 【发布时间】:2021-11-24 00:54:27 【问题描述】:Cloudfront 正在为根本不应该缓存的请求获取 RefreshHit。
它不应该被缓存,因为:
-
有
cache-control: max-age=0, no-store
;
最小 TTL 为 0;和
我已经创建了多个失效(在/*
)所以这个缓存的资源不是来自一些历史部署
知道为什么我会收到 RefreshHits 吗?
我还尝试将 Cache-Control 修改为 cache-control no-store, stale-if-error=0
,在 /*
上创建一个新的失效,现在我看到缓存命中(这次是在 Firefox 中):
【问题讨论】:
该页面建议启用“使用原始缓存标头”,这听起来与我们需要的完全一样,但该设置似乎只有在我们的行为上使用他们的“传统缓存设置”选项时才可用,但是我们正在使用新的“缓存策略和源请求策略(推荐)”选项。 不,因为我需要它来缓存来自我的源的一些请求,而不是其他请求,所以我真的需要它基于源提供的Cache-Control
指令来缓存它。 (用例不太相关,但它与我们整个站点从 jQuery 到 Next.js 的分段迁移有关)
是的,这是一个奇怪的用例。我们目前正在将我们的网站一次一个页面从不可缓存的、后端渲染的 jinja2/jQuery 转换为可缓存的、客户端渲染的 React/Next.js。如果我们可以控制所有约 100 个页面的行为,这样当一个转换到 Next.js 时,它会自动开始缓存,那将是非常好的。只有在过渡期间我们才有这个用例。
【参考方案1】:
在与支持人员进行了广泛交谈后,他们解释了发生了什么。
因此,如果您有 no-store
并且最小 TTL 为 0,那么 CloudFront 确实不会存储您的资源。但是,如果您的 Origin 需要很长时间才能响应(很可能在重负载下),而 CloudFront 等待对请求的响应,如果它收到另一个相同的请求(与缓存键相同),那么它将向两个请求发送一个响应。这是为了减轻服务器的负载。 (见docs)
虽然我在文档中没有看到,但支持人员称这些为“崩溃点击”。
因此,在为缓存的其他页面提供服务时,您似乎不能让单个行为服务于某些必须对每个请求具有唯一响应的页面。支持说:
我刚刚确认,使用 min TTL 0 和 cache-control: no-store,我们无法禁用折叠命中。如果确实需要完全禁用云端缓存,可以使用缓存策略 CachingDisabled
我们将为每个需要缓存的路径前缀创建一个行为。对于我们的用例,似乎没有比这更好的方法了(一次将我们的网站从不可缓存的、后端渲染的 jinja2/jQuery 转换为可缓存的、客户端渲染的 React/Next.js)。
【讨论】:
很高兴知道(关于负载下的行为)。至于缓存控制,我认为您希望将源上的缓存控制设置为max-age=0, must-revalidate, public
并确保您还可以发回一个 etag【参考方案2】:
对于 OP 的项目来说可能为时已晚,但我个人会使用一个简单的源响应 Lambda@Edge 函数以及 /* 和缓存策略的单个缓存行为来处理这个问题。您可以在源响应函数中编写所有过滤/缓存逻辑。这样一来,您只需在一个地方管理一点功能代码,而不是一堆单独的缓存行为(可能还有一堆缓存策略)。
例如,查找来自您的源的缓存控制响应标头的源响应函数。如果存在,则将其传递回客户端。但是,如果它不存在(或者如果您想用其他东西覆盖它),那么您可以在那里创建响应标头。边缘不关心缓存控制标头是来自您的源还是来自源响应 Lambda。到边缘,都是一样的。
【讨论】:
以上是关于即使使用缓存控制,来自云端的 RefreshHit:max-age=0, no-store的主要内容,如果未能解决你的问题,请参考以下文章
即使在成功连接并在 kafka 消费者控制台中获取消息后,也无法使用来自 kafka 主题的消息(使用 Python)[重复]