亚马逊云前缀的“Cache-Control: no-cache”头部在24小时后无效。

40

我在S3上托管一个静态网站,并使用Cloudfront缓存文件。我有三个文件,分别是:

  • index.html(Cache-Control:no-cache)
  • app.js(Cache-Control:max-age=63072000,public)
  • style.css(Cache-Control:max-age=63072000,public)

我的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文件失效。然后一整天都可以正常工作。第二天我又遇到了同样的问题。

这里发生了什么?

2个回答

67

请确认 CloudFront 分发的 最小TTL 是否设置为 0。 如果它设置为其他任何值,CloudFront 将不会遵循 no-cache 标头,并且仍将缓存该文件的 最小 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的问题。我发送的标头不一致。 - Adam
在将这些元标记添加到index.html文件后,是否有必要将最小TTL设置为0?我们可以为其他文件设置最小TTL> 0,但不适用于index.html吗? - Nirav Gandhi
如果您在CloudFront中定义了多个行为(例如一个用于index.html和另一个用于其他文件),则可以为“最小TTL”设置不同的值。但请记住,CloudFront中配置的“最小TTL”通常不是控制资源缓存时间的最佳解决方案。通常,您应该指定源服务器响应中生成的“Cache-Control”标头来控制这些内容,并将CloudFront的最小TTL值保持为0。 - dcro
24小时是Cloudfront的默认行为,无法被覆盖。好消息是,如果对象在源头没有发生变化,它将不会重新获取该对象,而是使用缓存中已经有的内容,并重新开始24小时的计时。 - fullstacklife
在定制选项中,最大TTL = 0似乎不可能实现,更改时间为24小时也是如此。 - Jordan
这个不起作用。我将Cache-Control设置为那样,但亚马逊没有更新任何内容。它会将其缓存一段不确定的时间。我的CloudFront设置缓存设置为“使用源缓存标头”。 - BradLaney

7

虽然这更像是一条评论,但有点过长。希望能对其他人有所帮助。

通过查询参数进行缓存破坏存在缺点,尽管也许可以通过Cloudfront行为来解决所有问题。请参见https://dev59.com/Nmkw5IYBdhLWcg3wus_K#24166106。尽管如此,我仍然建议使用唯一的文件名,例如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/

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接