即使使用缓存控制,来自云端的 RefreshHit:max-age=0,无存储

RefreshHit from cloudfront even with cache-control: max-age=0, no-store

Cloudfront 正在为根本不应缓存的请求获取 RefreshHit。

它不应该被缓存,因为:

  1. cache-control: max-age=0, no-store;
  2. 最小TTL为0;和
  3. 我已经创建了多个失效(在 /* 上)所以这个缓存的资源不是来自一些历史部署

知道我为什么会收到 RefreshHits 吗?

我还尝试将 Cache-Control 修改为 cache-control no-store, stale-if-error=0,在 /* 上创建一个新的失效,现在我看到缓存命中(这次是在 Firefox 中):

在与支持人员广泛交谈后,他们解释了发生了什么。

因此,如果您有 no-store 并且最小 TTL 为 0,那么 CloudFront 确实不会存储您的资源。但是,如果您的 Origin 需要很长时间才能响应(很可能在重负载下),而 CloudFront 等待对请求的响应,如果它收到另一个相同的请求(与缓存键相同),那么它会向两个请求发送一个响应。这是为了减轻服务器的负载。 (参见 docs

支持人员将这些称为“崩溃点击”,尽管我在文档中没有看到。

因此,您似乎无法让单个行为服务于某些页面,这些页面必须对每个请求具有唯一响应,同时服务于缓存的其他页面。支持说:

I just confirmed that, with min TTL 0 and cache-control: no-store, we cannot disable collapse hit. If you do need to fully disable cloudfront cache, you can use cache policy CachingDisabled

我们将为每个需要缓存的路径前缀创建一个行为。对于我们的用例来说,似乎没有比这更好的方法了(将我们的网站一次一页地从不可缓存的后端呈现 jinja2/jQuery 转换为可缓存的客户端呈现 React/Next .js).

对于 OP 的项目来说可能为时已晚,但我个人会用一个简单的 origin-response Lambda@Edge 函数以及 /* 和缓存策略的单一缓存行为来处理这个问题。您可以在 origin-response 函数中编写所有 filtering/caching 逻辑。这样你只在一个地方管理一个功能代码,而不是一堆单独的缓存行为(可能还有一堆缓存策略)。

例如,origin-response 函数查找来自您来源的 cache-control 响应 header。如果存在,则将其传回给客户端。但是,如果它不存在(或者如果您想用其他东西覆盖它),那么您可以在那里创建响应 header。 Edge 不关心 cache-control header 是来自你的来源,还是来自 origin-response Lambda。到边上,都一样