Amazon Cloudfront Cache-Control:no-cache 标头在 24 小时后无效

Posted

技术标签:

【中文标题】Amazon Cloudfront Cache-Control:no-cache 标头在 24 小时后无效【英文标题】:Amazon Cloudfront Cache-Control: no-cache header has no effect after 24 hours 【发布时间】:2013-09-17 10:02:40 【问题描述】:

我在 S3 中托管一个静态网站并使用 Cloudfront 来缓存文件。我基本上有 3 个带有以下标题的文件:

index.html(缓存控制:无缓存) app.js(缓存控制:max-age=63072000,公共) style.css(缓存控制:max-age=63072000,公共)

我的 html 文件使用的查询字符串参数会在我每次更新我的 css 或 js 文件时更新。我已经将 s3 配置为传递这些参数,并且我已经验证它可以使缓存的资源无效。我的 index.html 文件如下所示:

<html>
    <head>
        ...
        <link rel="stylesheet" href="app.css?v=14113e2c764">
    </head>
    <body>
        ...
        <script src="app.js?v=14113e2c764"></script>
    </body>
</html>

当我整天推送更新时,它似乎工作得很好,但是当我第二天早上来推送我的下一个更改时,index.html 文件已过期。它没有正确的 ?v= 参数,而是旧的!修复它的唯一方法是手动使 html 文件无效。然后在一天的剩余时间里一切正常。第二天我又遇到了同样的问题。

这是怎么回事?

【问题讨论】:

【参考方案1】:

验证 CloudFront 分配的 Minimum TTL 是否设置为 0。如果它设置为任何其他值,CloudFront 将不遵守 no-cache 标头,并且仍会缓存 Minimum TTL 的文件。可以在此处找到有关缓存指令的更多详细信息:

http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/Expiration.html

如果这没有帮助,请尝试调试index.html 的实际 HTTP 请求并在此处发布响应标头,以便我们查看它们。

另外,对于 index.html 文件,您可以尝试使用 no-cache,而不是使用

public, must-revalidate, proxy-revalidate, max-age=0

这将允许 CloudFront 将文件存储在边缘站点上,但它会强制它在每个请求中使用源重新验证它。如果文件未更改,CloudFront 将不需要从源传输文件的全部内容。这可以加快响应时间,尤其是对于较大的文件。

【讨论】:

看起来这是上传到 s3 的构建脚本中的竞争条件。我发送的标头不一致。 将这些元标记添加到 index.html 文件后是否需要将最小 TTL 设置为 0?我们可以让其他文件的最小 TTL > 0 但不是 index.html 吗? 如果您在 CloudFront 中定义了多个行为(例如,一个用于 index.html,另一个用于其余文件),您可以为 Minimum TTL 设置不同的值。请记住,在 CloudFront 中配置的 Minimum TTL 通常不是控制资源缓存时间的最佳解决方案。您通常应该在源服务器生成的响应中指定 Cache-Control 标头来控制这些响应并将 CloudFront 的最小 TTL 值保持为 0。 24 小时是 Cloudfront 的默认行为,不能以任何方式被覆盖。好消息是,如果对象在原点没有改变,它不会重新获取对象,它将使用缓存中的内容,并重新开始 24 小时制。 自定义选项中的最大 TTL = 0 似乎是可能的,以及从 24 小时开始更改时间。【参考方案2】:

这更像是一个评论,但有点太长了。希望能帮助到这里的其他人。

通过查询参数破坏缓存有一些缺点,但也许您可以通过 Cloudfront 行为来对抗它们。见https://***.com/a/24166106/630614。不过,我会推荐唯一的文件名,例如app.css?v=14113e2c764 变为 app.14113e2c764.css

回复 BradLaney 的评论/问题:如果您更新了缓存控制标头但没有看到更改,那是因为原始项目已被缓存 – 使其无效,您应该会看到下次查看资源时的新标题。

关于为 S3 项目设置缓存控制时的竞争条件,或者只是为 SPA 设置缓存控制,这对我的团队来说很有效:

# Sync all files with 1 week cache-control, excluding .html files.
aws s3 sync --cache-control 'max-age=604800' --exclude *.html dist/ s3://$AWS_BUCKET/
# Sync remaining .html files with no cache.
aws s3 sync --cache-control 'no-cache' dist/ s3://$AWS_BUCKET/

【讨论】:

以上是关于Amazon Cloudfront Cache-Control:no-cache 标头在 24 小时后无效的主要内容,如果未能解决你的问题,请参考以下文章

为啥需要 Amazon S3 和 Cloudfront?

Amazon S3 Cloudfront 部署最佳实践

使用 Amazon S3 和 Cloudfront 的 CORS

Amazon Cloudfront 缓存问题

如何为 Amazon CloudFront 签署 RTMP URL

将 Amazon 的 CloudFront 指向 A 记录而不是 CNAME