ChatGPT解决这个技术问题 Extra ChatGPT

强制 CloudFront 分发/文件更新

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

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

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

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

J
James Lawruk

好消息。亚马逊终于添加了一个失效功能。 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 请求,您也可以登录 Amazon 控制台并在那里创建一个无效请求:docs.amazonwebservices.com/AmazonCloudFront/latest/…
请记住,在您每月提出前 1,000 个无效请求后,每个文件的费用为 0.005 美元aws.amazon.com/cloudfront/pricing
@MichaelWarkentin 发出 API createInvalidation 请求后,我仍然看到更新需要 5-10 分钟左右才能失效。请注意,我在您发表此评论 4 年后写了此评论。
截至 2020 年,每条路径的成本为 0.005 美元,不再是文件。因此,如果您使 /* - 所有文件 之类的路径无效 - 无论文件/URL 的数量如何,您只需为一次无效付费。此外,AWS 每月免费提供 1000 条失效路径。请参阅 docs 中的无效请求
J
John K. Chow

截至 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 无用?
如果您只是使用 cloudfront 作为一种机制来拥有一个支持 SSL 的静态 S3 站点和一个自定义域,那么缓存就无关紧要了。此外,我们正在讨论的这些问题是,在开发阶段,0 时间缓存是好的。
a
anjanesh

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


这正是我一直在寻找的。当从 git 自动部署时,我将把它挂在 Beanstalkapp 的 web-hooks 中!感谢您的链接!
J
Josue Alexander Ibarra

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(或更高版本)作为运行时

第 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 边缘位置对其进行评估。

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

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


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

Bucket Explorer 现在有一个 UI,使这变得非常容易。就是这样:

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


s
samuraisam

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

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
M
MarcoP

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

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

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

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

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

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

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

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

像这样没有延迟失效并且没有成本!

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


F
Fábio Batista

在红宝石中,使用雾宝石

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 分钟


你刚刚救了我的命!
D
Dmitry Efimenko

当前 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 /*。我的也和你的一样,它并没有使分发无效......
D
DisgruntledGoat

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

这个新的无效器是:

完全在线(无需安装)

24x7 全天候可用(由 Google 托管)并且不需要任何会员资格。

有历史支持和路径检查,让您轻松地使文件无效。 (通常在第一次失效后只需点击几下!)

它也非常安全,您会在阅读其发布帖子时发现。

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


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

如果您使用 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 的发行说明。没有伤害,没有犯规。
J
Jay

转到 CloudFront。

单击您的 ID/分布。

单击失效。

单击创建失效。

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

完毕

https://i.stack.imgur.com/DgWVA.png