目标
无论多么陈旧,始终从 CDN EDGE 缓存中提供内容。尽可能在后台刷新它。
问题
我有一个NextJS应用程序,它在服务器端呈现一些 React 组件并将它们传递给客户端。对于这个讨论,让我们只考虑我的主页,它是未经身份验证的,对每个人来说都是一样的。
我想要的是将服务器呈现的主页缓存在 CDN 的 EDGE 节点上,并尽可能频繁地或总是从该缓存中向终端客户端提供服务。
根据我的阅读,正确支持缓存相关标头设置的 CDN(如 Fastly)Surrogate-Control
应该Cache-Control: stale-while-revalidate
能够做到这一点,但实际上,我并没有看到它像我期望的那样工作。我看到的是:
- 当先前的请求应该对其进行预热时,请求会错过缓存并返回原点
- 请求从缓存中提供,但在源发布新内容时永远不会更新
例子
考虑以下时间表:
[T0] - 访问者 1 请求www.mysite.com
- CDN 缓存完全冷,因此请求必须返回我的源 (AWS Lambda) 并重新计算主页。返回一个带有标题Surrogate-Control: max-age=100
和的响应Cache-Control: public, no-store, must-revalidate
。然后访问者 1 被提供主页,但他们不得不等待高达 5 秒!呸!愿没有其他访客遭受同样的命运。
[T50] - 访问者 2 请求www.mysite.com
- CDN 缓存包含我的文档并立即将其返回给访问者。他们只需要等待 40 毫秒!惊人的。在后台,CDN 从我的源站重新获取最新版本的主页。原来它没有改变。
[T80] -www.mysite.com
将新内容发布到主页,使任何缓存的内容真正过时。该网站的 V2 现已上线!
[T110] - 访问者 1 返回www.mysite.com
- 从 CDN 的角度来看,距离访问者 2 的请求仅 60 秒,这意味着访问者 2 发起的后台刷新应该会导致缓存中主页的一个 <100 秒的陈旧副本(尽管是 V1,而不是 V2 , 主页)。访问者 1 从缓存中获取 60 年代陈旧的 V1 主页。这次Visitor1的体验要好得多!本次请求发起后台刷新CDN缓存中的陈旧内容,本次origin返回网站V2(30s前发布)。
[T160] - 访客 3 访问www.mysite.com
- 尽管是新访客,但 CDN 缓存现在从访客 1 最近触发的后台刷新中恢复。为访问者 3 提供一个缓存的 V2 主页。
...
只要每 100 秒至少有 1 位访问者访问我的网站(因为max-age=100
),没有访问者会遭受到我的原点的完整往返等待时间。
问题
1.这是对现代 CDN 的合理要求吗?我无法想象这比总是返回原点(没有 CDN 缓存)更费力,但我一直在努力从任何 CDN 提供商那里找到有关正确方法的文档。我现在正在使用 Fastly,但我也愿意尝试其他任何方法(我先尝试了 Cloudflare,但读到他们不支持stale-while-revalidate
)
2.什么是正确的标题?(假设 CDN 提供商支持它们)我在 FastlySurrogate-Control: maxage=<X>
和Cache-Control: public, s-maxage=<X>, stale-while-revalidate
Cloudflare 中都玩过,但似乎没有一个正确地做到这一点(在 maxage 时间范围内很好地请求不要拾取源上的更改,直到出现缓存未命中)。
3.如果不支持,是否有 API 调用可以让我将内容更新推送到我的 CDN 的缓存层,有效地说“嘿,我刚刚发布了这个缓存键的新内容。就在这里!”
我可以使用 Cloudflare 工作人员使用他们的 KV 存储来实现这种自己的缓存,但我认为在为似乎很常见的问题实现代码解决方案之前,我需要做更多的研究。
提前致谢!