强制CloudFront分发/文件更新


146

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

有没有办法告诉Cloudfront发行版它需要刷新其文件或指出应刷新的单个文件?

亚马逊建议您对诸如logo_1.gif,logo_2.gif之类的文件进行版本控制,以解决此问题,但这似乎是一个非常愚蠢的解决方案。绝对没有其他方法吗?



作为旁注,我认为这样命名静态文件并不愚蠢。我们一直在使用它,并且在版本控制中按照文件版本进行自动重命名为我们节省了很多麻烦。
eis 2012年

1
@eis,除非您需要替换的文件已在线链接到1000个不同的位置。祝所有这些链接更新。
杰克·威尔逊

@Jakobud在这种情况下为什么要更新链接?他们指的是特定版本,如果文件已更改,则不是最新版本。如果文件没有更改,它将像以前一样工作。
eis 2012年

6
在某些情况下,如果公司收到律师事务所的撤消通知并必须替换文件,则在为某物或其他类型物品张贴错误图像时可能会犯错。仅上传具有新名称的新文件并不能解决该问题,不幸的是,这是当今越来越普遍的问题。
杰克·威尔逊

Answers:


134

好消息。亚马逊终于添加了无效功能。请参阅API参考

这是来自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>

9
请注意,失效将需要一些时间(根据我读过的一些博客文章,大约需要5-30分钟)。
Michael Warkentin,2012年

37
如果你不想让自己的API请求,您也可以登录亚马逊控制台和有创造的无效请求:docs.amazonwebservices.com/AmazonCloudFront/latest/...
j0nes

对于使用API​​进行失效的您来说,失效生效大约需要多长时间?
ill_always_be_a_warriors 2013年

20
请记住这个每人文件$ 0.005每月第一个1000个无效宣告请求后aws.amazon.com/cloudfront/pricing
TIMS

1
@MichaelWarkentin发出API createInvalidation请求后,我仍然看到更新需要5到10分钟左右的时间才能使更新无效。请注意,我在您发表4年后写此评论。
蒂姆·彼得森16-3-6

19

自3月19日起,Amazon现在允许Cloudfront的缓存TTL为0秒,因此(从理论上来说)您永远不会看到过时的对象。因此,如果您在S3中拥有资产,则只需转到AWS Web Panel => S3 => Edit Properties => Metadata,然后将“ Cache-Control”值设置为“ max-age = 0”。

这直接来自API文档

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


新的AWS Console界面中的此设置在哪里?我找不到
ill_always_be_a_warriors 2013年

1
我找到了单个文件的设置,但是是否要进行设置,以便上载到存储桶的任何东西的TTL为0?
ill_always_be_a_warriors

我当然也对存储桶范围的设置感兴趣,但是我发现这是一种更快/更好的解决方案。无效请求(以及API的其余部分)非常令人困惑,且记录不充分,因此我将车轮旋转了3个小时才立即生效。
2位炼金术士

33
叫我疯了,但是将TTL设置为0并将max-age设置为0确实是在不使用缓存的情况下使用CloudFront,这是否会将所有请求都转发到源服务器并不断检查更新?从根本上使CDN无效?
acidjazz

6
如果您只是将Cloudfront用作具有自定义域的已启用SSL的静态S3站点的机制,则缓存无关紧要。另外,我们正在讨论的这些问题是,在开发阶段,零时间缓存是好的。
Dan G


10

5分钟内自动完成更新设置

好,朋友们。现在执行自动CloudFront更新(失效)的最佳可能方法是创建Lambda函数,该函数将在每次将任何文件上传到S3存储桶(新文件或重写文件)时触发。

即使您以前从未使用过lambda函数,也确实很容易-只需按照我的分步说明进行操作,仅需5分钟:

第1步

转到https://console.aws.amazon.com/lambda/home,然后单击“ 创建lambda函数”

第2步

单击空白功能(自定义)

第三步

单击空(描边)框,然后从组合中选择S3

第4步

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

第5步

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

第6步

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

步骤7

选中启用触发器复选框,然后单击下一步

步骤8

命名您的函数(类似:YourBucketNameS3ToCloudFrontOnCreateAll

步骤9

选择Python 2.7(或更高版本)作为运行时

第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

设置处理程序:lambda_function.lambda_handler

步骤14

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

步骤15

单击查看策略文档,单击“ 编辑”,单击“ 确定”,然后将角色定义替换为以下内容(原样):

{
  "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。仔细检查在“ 现有角色”组合框中是否选中了刚创建的角色名称。

步骤17

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

步骤18

单击下一步,然后单击创建功能

步骤19

你已准备好出发!现在,每次将任何文件上传/重新上传到S3时,都会在所有CloudFront Edge位置对其进行评估。

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

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


只是每个S3批次中的最后一个项目?
菲尔(Phil)

@Phil以这种方式编写代码,因此仅新上传的文件将无效,而不是整个存储桶。如果是多文件上传,则每个文件将分别失效。奇迹般有效。
Kainax

该代码按预期运行的唯一原因是,S3当前每个通知仅包含一项,即,数组的长度始终为1,因此,即使您一次上传了多个文件,也会收到一个全新的通知每个文件。在任何情况下,您都不会收到整个存储桶的通知。但是,如果AWS更改了该行为,那么编写的代码尚不可用。编写处理整个数组(无论长度如何)的代码要安全得多,这是我最初的想法(非常遗憾)。
菲尔(Phil)

AWS添加事件处理程序的唯一原因是……很好……可以处理事件。他们为什么要删除它?无论如何添加新文件,它都应该触发API事件,这就是现在的工作方式,并且将继续正常工作。我使用AWS已有4年了,他们从未更改过任何东西,因此以前的代码停止工作。即使他们更改了API,他们也将其更改为新的独立版本,但始终保留所有以前的版本。在那种特殊情况下,我只是不相信个人文件事件将永远被删除。全球可能已有数百万个项目在使用它。
Kainax

如果我误解了您的第一个评论,而您的意思是“数量”:1将仅添加最后一个项目-数组中的每个项目都有FOR循环。
Kainax

9

Bucket Explorer具有一个UI,使现在变得非常容易。这是如何做:

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


4

如果您安装了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缓存时。顺便说一句,这是该帖子如何在travis部署到AWS期间重置\使CoudFront缓存无效
Mikita

3

只需发布信息即可通知访问此页面的任何人(“ Cloudfront File Refresh”的第一个结果)在swook.net上有一个易于使用且易于访问的在线无效器

这个新的无效器是:

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

全面披露:我做到了。玩得开心!


2
抱歉,但是即使“您说”这些凭证也没有存储或保存……一个人绝对不要将其凭证提供给第三者。可能实现了远程亚马逊身份验证或其他功能?
d.raev 2015年

您至少应将其放在https后面。
奥利弗·泰恩斯

联机工具通常很好用,但是向第三方工具提供凭据将是一个有效的安全问题。我建议使用官方Web控制台或官方CLI工具
RayLuo

2
为了他人的安全,我拒绝此答案。您永远都不应要求人们提供他们的证书
Moataz Elmasry

3

一种非常简单的方法是FOLDER版本控制。

因此,例如,如果您的静态文件有数百个,则只需将它们全部放入“ year + versioning”调用的文件夹中即可。

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

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

如果我想完全刷新,我只需将文件夹重命名为2014_v2到我的源文件中,并将php include内的内容更改为2014_v2

所有HTML都会自动更改并询问新路径,cloudfront MISS缓存并将其请求给源。

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

因此,PHP将此文件称为cloudfront.mydomain.com/2014_v1/javascript.js,当我想要完全刷新时,只需将文件夹重命名为“ 2014_v2”,然后通过将文件夹设置为“ 2014_v2”来更改PHP include。 。

像这样没有无效的延迟,没有成本!

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



2

在红宝石中,使用雾宝石

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分钟来处理和刷新


你才救了我的命!
法比奥·巴蒂斯塔

2

当前的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

1
我认为您需要在“ aws.invalidate”命令中使用星号,将其更改--paths /--paths /*。我的也像你一样,并且没有使发行无效……
Herald Smit

1

如果您使用的是AWS,则可能还会使用其官方CLI工具(较早或以后)。AWS CLI 1.9.12或更高版本支持使文件名列表无效。

全面披露:我做到了。玩得开心!


无效链接-导致404 :(由于发行说明(aws.amazon.com/releasenotes/?tag=releasenotes%23keywords%23cli)中缺少1.9.12版,我无法对其进行更新
SlyDave

杜德(thude)是将近3年前发布的版本。试用最新版本,该功能可能仍然存在。(全部披露:我不再在AWS CLI上工作。)
RayLuo

哦,我知道,只是发现所有发行说明中只有1.9.12不存在:D(这就是我无法更新链接的原因),这很奇怪。像对我一样,需要找到适用于AWS CLI的发行说明的人,此评论更像是一个提示。没有伤害,没有犯规。
SlyDave

0

转到CloudFront。

单击您的ID /分布。

单击无效。

单击创建无效。

在巨型示例框中,键入*,然后单击无效。

完成

在此处输入图片说明

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.