【问题标题】:Disable Cloudfront cache if file is not found如果未找到文件,则禁用 Cloudfront 缓存
【发布时间】:2020-07-16 08:09:51
【问题描述】:

我在 S3 存储桶前面创建了一个 Cloudfront 分配,如果未找到请求的文件,则使用 RoutingRule 重定向到 lambda 函数。我正在使用它来调整图像大小。

所需流量:

  1. 向 Cloudfront 请求文件
  2. 在 Cloudfront 检查 S3 中找不到文件
  3. 在 S3 中找不到文件重定向到 lambda 函数
  4. Lambda 将找到原始文件,调整其大小并重定向回 Cloudfront url。

s3 网站上的重定向规则集:

<RoutingRules>
  <RoutingRule>
    <Condition>
      <KeyPrefixEquals/>
      <HttpErrorCodeReturnedEquals>404</HttpErrorCodeReturnedEquals>
    </Condition>
    <Redirect>
      <Protocol>https</Protocol>
      <HostName>mylambda.execute-api.us-east-1.amazonaws.com</HostName>
      <ReplaceKeyPrefixWith>/?key=</ReplaceKeyPrefixWith>
      <HttpRedirectCode>307</HttpRedirectCode>
    </Redirect>
  </RoutingRule>
</RoutingRules>

当 lambda 函数重定向回原始 url 时,第 4 步出现问题 Cloudfront缓存了404?并且来自 S3 的路由规则再次重定向到导致循环的 lambda 函数。

  1. 我确认 lambda 函数生成了文件。
  2. 如果我使 Cloudfront 上的文件无效,我成功地看到它从 S3 提供)

我尝试将 0 TTL 添加到 404 错误页面,但没有帮助。

重定向规则返回 307 状态代码 [Temporary Redirect]。但我不知道如何为此设置 0 TTL。我在 Cloudfront 自定义错误响应页面上找不到该选项。

根据this article。 307 被缓存。需要为它设定一个规则……某处。

这是RoutingRules on AWS S3 Static website hosting的后续问题

感谢您的帮助。

更新: 1. 移除 S3 上的 RoutingRule 2. 为 Cloudfront 分发(API 网关)添加了一个新的源

lambda 函数现在返回

    return {
        statusCode: "200",
        body: "image converted",
    };

检查 Cloudwatch 日志我没有看到 lambda 函数被调用,当我转到 https://myCloudfront.cloudfront.net/photos/resized/test.jpg

我只看到一个普通的 404

我还为 404 添加了一个 0 TTL 的自定义错误页面

好消息是如果我通过 key=/photos/resized/test.jpg 去 api 网关 然后去https://my.cloudfront.net/photos/resized/test.jpg它工作。它可以正确读取图像。

我认为问题在于未触发 api 网关调用的故障转移。

【问题讨论】:

    标签: amazon-web-services amazon-s3 amazon-cloudfront


    【解决方案1】:

    我有相同的实现,也遇到了同样的问题。但是,这是我的解决方案:

    1. 在成功响应上的 lambda 函数上添加 headers 设置 cache-controlmust-revalidate, proxy-revalidate 看起来像这样。 { "headers": { "cache-control": "must-revalidate, proxy-revalidate" } }。这将强制重新验证您刚刚制作的文件。
    2. 可选)转到您的 CloudFront Distribution -> 错误页面 -> 创建自定义错误响应 然后将 HTTP 错误代码 400 的 TTL 设置为 0,这将终止来自 CloudFront 的缓存错误。

    注意:这里的权衡是创建新维度变得明显时的等待时间。

    【讨论】:

      【解决方案2】:

      当然,您可以使用 Lambda@Edge 原始响应触发器来修改响应并设置所需的标头。从某种意义上说,这将是“最正确”,因此也是“最理想”的解决方案,但仅在理论上,因为它引入了不必要的成本和复杂性。

      默认 TTL 是 CloudFront 在内部使用的值,当没有找到 Cache-Control 响应标头时...因此,您可以将其设置为 0 并在创建 S3 对象时包含正确的 Cache-Control 标头,所以除非重定向,否则不会使用默认 TTL。我不喜欢的是没有标题坚持浏览器也不缓存重定向。

      但您实际上并不需要在此处向浏览器返回重定向。你根本不需要重定向。

      借助 CloudFront 的源故障转移功能,您可以为您的分配设置两个源 - 主源和辅助源,以便在 CloudFront 检测到您的主源不可用时从您的辅助源提供您的内容。

      https://aws.amazon.com/about-aws/whats-new/2018/11/amazon-cloudfront-announces-support-for-origin-failover/

      “不可用”这个词在这里是不必要的模糊,因为这个功能做的不止这些,它会做你想做的事。设置触发源“故障转移”的内容...

      您可以选择以下状态码的任意组合:500、502、503、504、404 或 403。

      https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/high_availability_origin_failover.html#concept_origin_groups.creating

      所以只需要正常的存储桶行为就足够了,不需要重定向规则。

      请注意,使用此设置,最终响应是唯一可以由 CloudFront 缓存的内容 - 无论该响应来自主要 (S3) 还是辅助(通过 API 网关的 Lambda)来源 - 所以这消除了问题缓存瞬态响应。

      另请注意,尽管使用了“故障转移”一词,但 CloudFront 并不维护源状态的概念模型,因此每个请求都独立存在,即使其他请求“失败。”

      【讨论】:

      • 谢谢你,迈克尔。这看起来很有希望。但是假设有两个来源,从技术上讲,请求的文件还不存在(lambda 生成它然后将其保存到 s3 中)如何指定故障转移是相同的来源,但在 lambda 生成文件之后?你还说我不需要重定向。您的意思是没有存储桶重定向,但仍然需要 lambda 重定向,对吗?
      • 故障转移是 API 网关和 Lambda 函数,它接收存储桶以 403/404 回答的请求,完成工作,然后使用适当的 Cache-Control 标头将浏览器重定向回来,或者只返回将其存储在存储桶中后生成的对象有效负载 - 假设它小于 Lambda 有效负载限制。这里的要点是不需要重定向到 Lambda 函数,因为 CloudFront 会自动尝试从备用源获取原始路径。
      • 哦,我明白了。以及如何告诉 lambda 函数要处理哪个文件? lambda 现在正在使用: const key = event.queryStringParameters.key;这来自存储桶中的 /?key= 。如果 cloudfront 将直接命中 api 网关,将通过什么键?
      • 原始请求路径将在 API 网关接收,因此您需要稍微不同的处理方式。
      • 非常感谢您的帮助。我们将到达那里:) 所以.. lambda 函数不应该再重定向到云端?将图像转换并保存在正确的路径后应该返回什么?
      猜你喜欢
      • 2018-05-03
      • 2014-06-09
      • 2017-03-03
      • 2016-02-01
      • 2019-03-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多