强制 CloudFront 分发/文件更新

Posted

技术标签:

【中文标题】强制 CloudFront 分发/文件更新【英文标题】:Force CloudFront distribution/file update 【发布时间】:2010-11-19 02:00:14 【问题描述】:

我正在使用 Amazon 的 CloudFront 来提供我的 Web 应用程序的静态文件。

有没有办法告诉云端分发它需要刷新它的文件或指出应该刷新的单个文件?

亚马逊建议您对您的文件进行版本控制,例如 logo_1.gif、logo_2.gif 等,作为解决此问题的方法,但这似乎是一个非常愚蠢的解决方案。就没有别的办法了吗?

【问题讨论】:

How can I update files on Amazon's CDN (CloudFront)? 的可能重复项 作为旁注,我认为这样命名静态文件并不愚蠢。我们一直在使用它,并且在版本控制中根据文件版本自动重命名为我们省去了很多麻烦。 @eis 除非您需要替换的文件已在线链接到 1000 个不同的地方。祝所有这些链接更新好运。 @Jakobud 为什么要在这种情况下更新链接?如果文件已更改,他们指的是特定版本,这不是最新的。如果文件未更改,它将像以前一样工作。 在某些情况下,公司可能会错误地为某物或某些其他类型的项目发布错误的图像,从而收到律师事务所的删除通知并不得不更换文件。简单地用新名称上传新文件并不能解决这类问题,不幸的是,这个问题如今越来越普遍。 【参考方案1】:

好消息。亚马逊终于添加了一个失效功能。 See the API Reference.

这是来自 API 参考的示例请求:

POST /2010-08-01/distribution/[distribution ID]/invalidation HTTP/1.0
Host: cloudfront.amazonaws.com
Authorization: [AWS authentication string]
Content-Type: text/xml

<InvalidationBatch>
   <Path>/image1.jpg</Path>
   <Path>/image2.jpg</Path>
   <Path>/videos/movie.flv</Path>
   <CallerReference>my-batch</CallerReference>
</InvalidationBatch>

【讨论】:

请注意,失效需要一些时间(根据我读过的一些博客文章,显然需要 5-30 分钟)。 如果您不想自己发出 API 请求,您也可以登录亚马逊控制台并在那里创建一个无效请求:docs.amazonwebservices.com/AmazonCloudFront/latest/… 请记住,在您每月收到前 1000 个无效请求后,每个文件的费用为 0.005 美元aws.amazon.com/cloudfront/pricing @MichaelWarkentin 发出 API createInvalidation 请求后,我仍然看到更新需要 5-10 分钟左右才能失效。请注意,我在您发表此评论 4 年后写了此评论。 自 2020 年起,每个路径的成本为 0.005 美元,不再是文件。因此,如果您使/* 之类的路径无效 - 所有文件 - 无论文件/URL 的数量如何,您只需支付一次无效费用。此外,AWS 每月免费提供 1000 条失效路径。请参阅docs 中的无效请求【参考方案2】:

从 3 月 19 日起,亚马逊现在允许 Cloudfront 的缓存 TTL 为 0 秒,因此您(理论上)应该永远不会看到过时的对象。因此,如果您的资产在 S3 中,您只需转到 AWS Web 面板 => S3 => 编辑属性 => 元数据,然后将“Cache-Control”值设置为“max-age=0”。

这是直接来自API documentation:

要控制 CloudFront 是否缓存对象以及缓存多长时间,我们建议您将 Cache-Control 标头与 max-age= 指令一起使用。 CloudFront 将对象缓存指定的秒数。 (最小值为 0 秒。)

【讨论】:

此设置在新 AWS 控制台 UI 中的什么位置?我找不到它。 我找到了单个文件的设置,但是否有设置可以使上传到我的存储桶的任何内容的 TTL 为 0? 虽然我也肯定对存储桶范围的设置感兴趣,但我发现这是一个更快/更好的解决方案。无效请求(以及 API 的其余部分)非常令人困惑且记录不充分,我旋转了 3 个小时,然后立即生效。 叫我疯了,但是将 TTL 设置为 0 并将 max-age 设置为 0 真的是在使用 CloudFront 而没有缓存,那不是将所有请求转发到源端不断检查更新吗?本质上使 CDN 无用? 如果您只是使用云端作为一种机制来拥有一个支持 SSL 的静态 S3 站点和一个自定义域,那么缓存并不重要。此外,我们正在讨论的这些问题是,在开发阶段,0-time 缓存是好的。【参考方案3】:

使用 Invalidation API,它确实会在几分钟内更新。 查看php Invalidator。

【讨论】:

这正是我想要的。当从 git 自动部署时,我将把它挂在 Beanstalkapp 的 web-hooks 中!感谢您的链接!【参考方案4】:

5 分钟内自动更新设置

好的,伙计们。目前执行自动 CloudFront 更新(失效)的最佳方法是创建 Lambda 函数,每次将任何文件上传到 S3 存储桶(新文件或重写)时都会触发该函数。

即使您以前从未使用过 lambda 函数,它也非常简单——只需按照我的分步说明操作,只需 5 分钟:

第 1 步

转到https://console.aws.amazon.com/lambda/home 并点击创建 lambda 函数

第 2 步

点击空白函数(自定义)

第 3 步

点击空白(描边)框并从组合中选择S3

第 4 步

选择您的存储桶(与 CloudFront 分配相同)

第 5 步

事件类型设置为“对象已创建(全部)”

第 6 步

设置前缀和后缀,如果您不知道它是什么,则将其留空。

第 7 步

选中启用触发器复选框并点击下一步

第 8 步

为您的函数命名(例如:YourBucketNameS3ToCloudFrontOnCreateAll

第 9 步

选择Python 2.7(或更高版本)作为Runtime

第 10 步

粘贴以下代码而不是默认的 python 代码:

from __future__ import print_function

import boto3
import time

def lambda_handler(event, context):
    for items in event["Records"]:
        path = "/" + items["s3"]["object"]["key"]
        print(path)
        client = boto3.client('cloudfront')
        invalidation = client.create_invalidation(DistributionId='_YOUR_DISTRIBUTION_ID_',
            InvalidationBatch=
            'Paths': 
            'Quantity': 1,
            'Items': [path]
            ,
            'CallerReference': str(time.time())
            )

第 11 步

在新的浏览器选项卡中打开 https://console.aws.amazon.com/cloudfront/home 并复制您的 CloudFront 分配 ID 以供下一步使用。

第 12 步

返回 lambda 选项卡并在 Python 代码中粘贴您的分发 ID,而不是 _YOUR_DISTRIBUTION_ID_。保留周围的引号。

第 13 步

设置handler:lambda_function.lambda_handler

第 14 步

点击角色组合框并选择创建自定义角色。将打开浏览器中的新标签页。

第 15 步

点击view policy document,点击edit,点击OK并将角色定义替换为以下(原样):


  "Version": "2012-10-17",
  "Statement": [
    
      "Effect": "Allow",
      "Action": [
        "logs:CreateLogGroup",
        "logs:CreateLogStream",
        "logs:PutLogEvents"
      ],
      "Resource": "arn:aws:logs:*:*:*"
    ,
    
      "Effect": "Allow",
      "Action": [
          "cloudfront:CreateInvalidation"
      ],
      "Resource": [
          "*"
      ]
    
  ]

第 16 步

点击允许。这将使您返回一个 lambda。仔细检查您刚刚创建的角色名称是否已在 Existing role 组合框中选择。

第 17 步

内存 (MB) 设置为 128 并将 超时 设置为 5 秒。

第 18 步

点击下一步,然后点击创建函数

第 19 步

你可以走了!现在,每次您将任何文件上传/重新上传到 S3 时,都会在所有 CloudFront 边缘位置对其进行评估。

PS - 当您进行测试时,请确保您的浏览器正在从 CloudFront 加载图像,而不是从本地缓存。

PSS - 请注意,每月只有前 1000 个文件失效是免费的,每个超出限制的失效费用为 0.005 美元。 Lambda 函数也可能会收取额外费用,但非常便宜。

【讨论】:

只是每个 S3 批次的最后一项? @Phil 代码是这样编写的,所以只有新上传的文件才会失效,而不是整个存储桶。如果上传多个文件,每个文件将分别失效。像魅力一样工作。 此代码按预期工作的唯一原因是因为 S3 目前每个通知只包含一项,即数组的长度总是 1,因此,即使您在一个文件中上传多个文件去吧,每个文件都会收到一个全新的通知。在任何情况下,您都不会收到整个存储桶的通知。尽管如此,如果 AWS 改变这种行为,所编写的代码还没有准备好。编写处理整个数组的代码要安全得多,无论长度如何,这是我最初(遗憾地错过)的观点。 AWS 添加事件处理程序的唯一原因是......好吧......处理事件。他们为什么要删除它?无论如何添加新文件,它都应该触发 API 事件,这就是它现在的工作方式并将继续工作。我使用 AWS 已经 4 年了,他们从来没有改变过什么,所以以前的代码停止了工作。即使他们更改 API,他们也将其更改为新的独立版本,但始终支持所有以前的版本。在那种特殊情况下,我只是不相信个人文件事件会被删除。它可能已经被全球数百万个项目使用。 如果我误解了您的第一条评论并且您的意思是 'Quantity': 1 将仅添加最后一项 - 数组中的每个项都有 FOR 循环。 【参考方案5】:

Bucket Explorer 的 UI 现在让这一切变得非常简单。方法如下:

右键单击您的存储桶。选择“管理分发”。 右键单击您的发行版。选择“获取 Cloudfront 失效列表” 然后选择“创建”以创建新的失效列表。 选择要失效的文件,然后单击“失效”。等待 5-15 分钟。

【讨论】:

【参考方案6】:

如果您安装了boto(它不仅适用于 python,还安装了许多有用的命令行实用程序),它提供了一个命令行实用程序,专门称为cfadmin 或“cloud front admin”,它提供以下功能:

Usage: cfadmin [command]
cmd - Print help message, optionally about a specific function
help - Print help message, optionally about a specific function
invalidate - Create a cloudfront invalidation request
ls - List all distributions and streaming distributions

你通过运行使事物无效:

$sam# cfadmin invalidate <distribution> <path>

【讨论】:

其实 cfadmin 是一个非常有用的工具,尤其是当您需要从 console\bash\travis ci 部署脚本重置 CloudFront 缓存时。顺便说一句,这里是post how to reset\invalidate CoudFront cache during the travis deployment to aws【参考方案7】:

一个非常简单的方法是文件夹版本控制。

因此,例如,如果您的静态文件有数百个,只需将它们全部放入一个名为 year+versioning 的文件夹中。

例如,我使用一个名为 2014_v1 的文件夹,里面有我所有的静态文件...

所以在我的 html 中,我总是将引用放在文件夹中。 (当然我有一个 PHP 包含,我在其中设置了文件夹的名称。)因此,通过更改 1 个文件,它实际上会更改我所有的 PHP 文件..

如果我想要完全刷新,我只需将文件夹重命名为 2014_v2 到我的源代码中,然后将 php 包含更改为 2014_v2

所有 HTML 自动更改并询问新路径,云端 MISS 缓存并向源请求。

示例: SOURCE.mydomain.com 是我的来源, cloudfront.mydomain.com 是云端分发的 CNAME。

所以 PHP 调用了这个文件 cloudfront.mydomain.com/2014_v1/javascript.js 当我想要完全刷新时,只需将文件夹重命名为“2014_v2”,然后通过将文件夹设置为“2014_v2”来更改 PHP 包含。

这样就不会延迟失效并且没有成本!

这是我在***的第一篇文章,希望我做得很好!

【讨论】:

【参考方案8】:

在红宝石中,使用雾宝石

AWS_ACCESS_KEY = ENV['AWS_ACCESS_KEY_ID']
AWS_SECRET_KEY = ENV['AWS_SECRET_ACCESS_KEY']
AWS_DISTRIBUTION_ID = ENV['AWS_DISTRIBUTION_ID']

conn = Fog::CDN.new(
    :provider => 'AWS',
    :aws_access_key_id => AWS_ACCESS_KEY,
    :aws_secret_access_key => AWS_SECRET_KEY
)

images = ['/path/to/image1.jpg', '/path/to/another/image2.jpg']

conn.post_invalidation AWS_DISTRIBUTION_ID, images

即使失效,在所有亚马逊边缘服务器上处理和刷新失效仍然需要 5-10 分钟

【讨论】:

你刚刚救了我的命!【参考方案9】:

当前 AWS CLI 在预览模式下支持失效。在控制台中运行一次:

aws configure set preview.cloudfront true

我使用 npm 部署我的 Web 项目。我的package.json 中有以下脚本:


    "build.prod": "ng build --prod --aot",
    "aws.deploy": "aws s3 sync dist/ s3://www.mywebsite.com --delete --region us-east-1",
    "aws.invalidate": "aws cloudfront create-invalidation --distribution-id [MY_DISTRIBUTION_ID] --paths /*",
    "deploy": "npm run build.prod && npm run aws.deploy && npm run aws.invalidate"

有了上面的脚本,您就可以部署您的网站了:

npm run deploy

【讨论】:

我认为您需要在“aws.invalidate”命令中使用星号,将--paths / 更改为--paths /*。我的也和你的一样,它并没有使分发无效......【参考方案10】:

设置 TTL=1 小时并替换

http://developer.amazonwebservices.com/connect/ann.jspa?annID=655

【讨论】:

【参考方案11】:

只是发布通知访问此页面的任何人(“Cloudfront 文件刷新”的第一个结果) 有一个易于使用的+访问online invalidator available at swook.net

这个新的无效器是:

完全在线(无需安装) 24x7 全天候可用(由 Google 托管),不需要任何会员资格。 支持历史记录和路径检查,让您轻松地使文件无效。 (通常在第一次失效后只需点击几下!) 它也非常安全,您在阅读它的release post 时就会发现。

完全披露:我做了这个。玩得开心!

【讨论】:

对不起,但即使“你说”没有存储或泄露的凭据......一个人永远不应该将他的凭据提供给第 3 方。可能是实施远程亚马逊身份验证之类的吗? 你至少应该把它放在 https 后面。 在线工具通常不错,但向 3rd 方工具提供凭据将是一个有效的安全问题。我建议使用官方网络控制台或official CLI tool。 为了他人的安全,我不赞成这个答案。您永远不应该要求人们提供他们的凭据【参考方案12】:

如果您使用的是 AWS,您可能还会使用其官方 CLI 工具(迟早)。 AWS CLI version 1.9.12 及以上版本支持文件名列表失效。

完全披露:我做了这个。玩得开心!

【讨论】:

死链接 - 导致 404 :( 我无法更新它,因为发行说明中缺少 1.9.12 版 (aws.amazon.com/releasenotes/?tag=releasenotes%23keywords%23cli) 老兄,那是大约 3 年前发布的版本。尝试最新版本,该功能可能仍然存在。 (完全披露:我不再使用 AWS CLI。) 哦,我知道,只是觉得奇怪的是,在所有发行说明中,只有 1.9.12 不存在:D(这是我无法更新链接的原因)。该评论更像是对任何在这里找到方式的人的暗示,就像我所做的那样,并且需要找到 AWS CLI 的发行说明。没有伤害,没有犯规。【参考方案13】:

转到 CloudFront。

点击你的 ID/Distributions。

点击失效。

点击创建失效。

在巨型示例框中输入 * 并单击无效

完成

【讨论】:

以上是关于强制 CloudFront 分发/文件更新的主要内容,如果未能解决你的问题,请参考以下文章

AWS Cloudfront 分发保持“进行中”55 分钟并计数

在 Cloudfront 自定义错误响应中,有没有办法强制更新浏览器导航栏的重定向?

Apple 在 S3 上的 apple-app-site-association 文件与 CloudFront 分发

具有相同域名的 Webserver 和 Cloudfront 分发

将 Cloudfront 添加到 S3

S3 + Cloudfront 上的浏览​​器缓存破坏