CloudFront / S3 ETag:CloudFront 可以在 CF TTL 过期之前发送更新的 S3 Object 吗?
CloudFront / S3 ETag: Possible for CloudFront to send updated S3 Object before the CF TTL has expired?
我有一个关于 CloudFront 将如何使用 S3 object 的 ETag 来确定是否需要发送刷新的 object 的问题与否。
我知道 ETag 将成为 CloudFront 分发请求的一部分,在我的例子中,我看到的是“弱”(缩短)版本:
if-none-match: W/"eabcdef4036c3b4f8fbf1e8aa81502542"
如果发送的这个 ETag 与 S3 Object 的当前 ETag 值不匹配,则 CloudFront 将发送最新版本。
我看到这项工作按预期进行,但只有在达到 CloudFront 的缓存策略之后。在我的例子中,它被设置为 20 分钟。
具有缓存策略的 CloudFront:
- 最小 TTL:1
- 最大 TTL:1200 <--(20 分钟)
- 默认 TTL:900
- 未设置源请求策略
S3 存储桶:
- 设置为仅允许通过相应的 CloudFront 进行访问
以上分布。
- 桶和 object 不是 public
- 测试 object (index.html) 在这种情况下只有一个 header 集合:
Content-Type = text/html
- 虽然我在使用 CloudFront 的缓存策略,但我也测试过
使用 Cache-Control 的 S3 Object header = max-age=6000
- 这对“index.html”object 中的刷新没有影响
关于我要问的 ETag 检查。
场景:
在第一次“putObject”到那个 S3 存储桶时,“index.html”文件的 ETag 为:
eabcdef4036c3b4f8fbf1e8aa81502542
当我为那个“index.html”文件点击 URL (GET) 时,有效启动了 20 分钟的缓存。
对“index.html”的后续点击 URL (GET) 具有值为
的请求
if-none-match: W/"eabcdef4036c3b4f8fbf1e8aa81502542"
我还在返回的响应中看到“x-cache:从云端命中”。
在 20 分钟之前,我将通过代码中的“putObject”命令更改“index.html”文件和 re-upload。
这会将 ETag 更改为:
exyzcde4099c3b4f8fuy1e8aa81501122
然后我希望对 CloudFront 的下一个请求,在 20 分钟 TTL 和旧的“if-none-match" 值,然后会提示 CloudFront 查看 ETag 不同并发送最新版本。
但总的来说 cases/tests 它没有。 CloudFront 似乎会忽略 ETag 差异并继续发送旧的“index.html”版本。
只有在 20 分钟(缓存 TTL)结束后,CloudFront 才会发送最新版本。
当时Request中的ETagchanges/updates也是:
if-none-match: W/"exyzcde4099c3b4f8fuy1e8aa81501122"
问题(终于,嗯?):
有没有办法配置 CloudFront 以侦听传入的 ETag,如果需要,发送最新的 Object 而无需等待缓存策略 TTL 过期?
更新:
Kevin Henry 的回复很好地解释了这一点:
"CloudFront 不知道您更新了 S3。您告诉它在 TTL 过期之前不要检查源。所以它只是提供旧文件,直到 TTL 过期并且它看到你上传到 S3 的新的。(请注意,这与 ETag 没有任何关系)。"
因此,我决定测试如果我将所有三个 CloudFront 设置的 CloudFront 缓存策略的 TTL 都设置为 0,将如何使用 ETag。我知道这违背了 CloudFront 的目的和优势之一,但我仍在思考 CDN 缓存的某些关键方面。
将缓存设置为 0 后,我在返回的响应中看到连续的“来自 CloudFront 的小姐”。
我预料到了这一点,在第一个响应中我看到了 200 的 HTTP 状态。请注意,returned 的文件大小对于此测试是 128KB。
对该同一文件的后续调用 return HTTP 状态 304,文件大小 return 约为 400B。
我一更新 S3 存储桶中的“index.html”文件,并调用相同的 URL,状态代码为 200,文件大小为 128KB。
后续调用 return 状态 304,平均文件大小再次为 400B。
再次查看 304 HTTP 状态的定义:
"已收到条件 GET 或 HEAD 请求,如果不是因为条件评估为 false,将导致 200 OK 响应。
换句话说,服务器不需要传输目标资源的表示,因为请求表明使请求有条件的客户端已经具有有效的表示;因此,服务器重定向客户端以使用该存储的表示,就好像它是 200 OK 响应的有效负载一样。"
所以我是对的n 认为此时我正在使用浏览器的缓存?
对 CloudFront 的调用现在会将请求传递给 Origin,其中 ETag 用于验证资源是否已更改。
如果没有,则 return 编辑 304 并且浏览器启动并return存储它的“index.html”版本。
这是一个正确的假设吗?
如果您想知道,我不能使用失效方法来清除缓存,因为我的网站每天可能会发生数千次失效。我正在托管一个写作期刊网站,作者可以在那里每天更新他们的文件,从而在 S3 上生成他们作品的新版本。
我也不想使用版本控制方法,将时间戳或其他字符串作为查询添加到页面 URL。主要是这一个SEO原因。
我的理想情况是在作者更新之前提供同一版本的作品,此时对同一页面的下一次调用将显示其最新版本。
这 research/exercise 正在帮助我学习和权衡我的选择。
再次感谢 help/input。
乔恩
"我希望在 20 分钟 TTL 之前和使用旧 if-none-match
值的下一个对 CloudFront 的请求会提示 CloudFront查看 ETag
不同并发送最新版本。"
这是一个错误的假设。 CloudFront 不知道您更新了 S3。你告诉它在 TTL 过期之前不要检查源。所以它只是提供旧文件,直到 TTL 过期并且它看到您上传到 S3 的新文件。 (请注意,这与 ETags
没有任何关系)。
CloudFront 确实提供了 invalidate the cache, and you can read more about how to combine that with S3 updates in these answers.
的方法
我有一个关于 CloudFront 将如何使用 S3 object 的 ETag 来确定是否需要发送刷新的 object 的问题与否。
我知道 ETag 将成为 CloudFront 分发请求的一部分,在我的例子中,我看到的是“弱”(缩短)版本:
if-none-match: W/"eabcdef4036c3b4f8fbf1e8aa81502542"
如果发送的这个 ETag 与 S3 Object 的当前 ETag 值不匹配,则 CloudFront 将发送最新版本。
我看到这项工作按预期进行,但只有在达到 CloudFront 的缓存策略之后。在我的例子中,它被设置为 20 分钟。
具有缓存策略的 CloudFront:
- 最小 TTL:1
- 最大 TTL:1200 <--(20 分钟)
- 默认 TTL:900
- 未设置源请求策略
S3 存储桶:
- 设置为仅允许通过相应的 CloudFront 进行访问 以上分布。
- 桶和 object 不是 public
- 测试 object (index.html) 在这种情况下只有一个 header 集合: Content-Type = text/html
- 虽然我在使用 CloudFront 的缓存策略,但我也测试过 使用 Cache-Control 的 S3 Object header = max-age=6000
- 这对“index.html”object 中的刷新没有影响 关于我要问的 ETag 检查。
场景:
在第一次“putObject”到那个 S3 存储桶时,“index.html”文件的 ETag 为:
eabcdef4036c3b4f8fbf1e8aa81502542
当我为那个“index.html”文件点击 URL (GET) 时,有效启动了 20 分钟的缓存。
对“index.html”的后续点击 URL (GET) 具有值为
的请求if-none-match: W/"eabcdef4036c3b4f8fbf1e8aa81502542"
我还在返回的响应中看到“x-cache:从云端命中”。
在 20 分钟之前,我将通过代码中的“putObject”命令更改“index.html”文件和 re-upload。
这会将 ETag 更改为:
exyzcde4099c3b4f8fuy1e8aa81501122
然后我希望对 CloudFront 的下一个请求,在 20 分钟 TTL 和旧的“if-none-match" 值,然后会提示 CloudFront 查看 ETag 不同并发送最新版本。
但总的来说 cases/tests 它没有。 CloudFront 似乎会忽略 ETag 差异并继续发送旧的“index.html”版本。
只有在 20 分钟(缓存 TTL)结束后,CloudFront 才会发送最新版本。
当时Request中的ETagchanges/updates也是:
if-none-match: W/"exyzcde4099c3b4f8fuy1e8aa81501122"
问题(终于,嗯?):
有没有办法配置 CloudFront 以侦听传入的 ETag,如果需要,发送最新的 Object 而无需等待缓存策略 TTL 过期?
更新:
Kevin Henry 的回复很好地解释了这一点:
"CloudFront 不知道您更新了 S3。您告诉它在 TTL 过期之前不要检查源。所以它只是提供旧文件,直到 TTL 过期并且它看到你上传到 S3 的新的。(请注意,这与 ETag 没有任何关系)。"
因此,我决定测试如果我将所有三个 CloudFront 设置的 CloudFront 缓存策略的 TTL 都设置为 0,将如何使用 ETag。我知道这违背了 CloudFront 的目的和优势之一,但我仍在思考 CDN 缓存的某些关键方面。
将缓存设置为 0 后,我在返回的响应中看到连续的“来自 CloudFront 的小姐”。
我预料到了这一点,在第一个响应中我看到了 200 的 HTTP 状态。请注意,returned 的文件大小对于此测试是 128KB。
对该同一文件的后续调用 return HTTP 状态 304,文件大小 return 约为 400B。
我一更新 S3 存储桶中的“index.html”文件,并调用相同的 URL,状态代码为 200,文件大小为 128KB。
后续调用 return 状态 304,平均文件大小再次为 400B。
再次查看 304 HTTP 状态的定义:
"已收到条件 GET 或 HEAD 请求,如果不是因为条件评估为 false,将导致 200 OK 响应。
换句话说,服务器不需要传输目标资源的表示,因为请求表明使请求有条件的客户端已经具有有效的表示;因此,服务器重定向客户端以使用该存储的表示,就好像它是 200 OK 响应的有效负载一样。"
所以我是对的n 认为此时我正在使用浏览器的缓存?
对 CloudFront 的调用现在会将请求传递给 Origin,其中 ETag 用于验证资源是否已更改。
如果没有,则 return 编辑 304 并且浏览器启动并return存储它的“index.html”版本。
这是一个正确的假设吗?
如果您想知道,我不能使用失效方法来清除缓存,因为我的网站每天可能会发生数千次失效。我正在托管一个写作期刊网站,作者可以在那里每天更新他们的文件,从而在 S3 上生成他们作品的新版本。
我也不想使用版本控制方法,将时间戳或其他字符串作为查询添加到页面 URL。主要是这一个SEO原因。
我的理想情况是在作者更新之前提供同一版本的作品,此时对同一页面的下一次调用将显示其最新版本。
这 research/exercise 正在帮助我学习和权衡我的选择。
再次感谢 help/input。
乔恩
"我希望在 20 分钟 TTL 之前和使用旧 if-none-match
值的下一个对 CloudFront 的请求会提示 CloudFront查看 ETag
不同并发送最新版本。"
这是一个错误的假设。 CloudFront 不知道您更新了 S3。你告诉它在 TTL 过期之前不要检查源。所以它只是提供旧文件,直到 TTL 过期并且它看到您上传到 S3 的新文件。 (请注意,这与 ETags
没有任何关系)。
CloudFront 确实提供了 invalidate the cache, and you can read more about how to combine that with S3 updates in these answers.
的方法