Force CloudFront distribution/file update

2019-01-16 00:02发布

I'm using Amazon's CloudFront to serve static files of my web apps.

Is there no way to tell a cloudfront distribution that it needs to refresh it's file or point out a single file that should be refreshed?

Amazon recommend that you version your files like logo_1.gif, logo_2.gif and so on as a workaround for this problem but that seems like a pretty stupid solution. Is there absolutely no other way?

12条回答
太酷不给撩
2楼-- · 2019-01-16 00:33

Good news. Amazon finally added an Invalidation Feature. See the API Reference.

This is a sample request from the API Reference:

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>
查看更多
聊天终结者
3楼-- · 2019-01-16 00:35

If you are using AWS, you probably also use its official CLI tool (sooner or later). AWS CLI version 1.9.12 or above supports invalidating a list of file names.

Full disclosure: I made this. Have fun!

查看更多
劳资没心,怎么记你
4楼-- · 2019-01-16 00:36

Automated update setup in 5 mins

OK, guys. The best possible way for now to perform automatic CloudFront update (invalidation) is to create Lambda function that will be triggered every time when any file is uploaded to S3 bucket (a new one or rewritten).

Even if you never used lambda functions before, it is really easy -- just follow my step-by-step instructions and it will take just 5 mins:

Step 1

Go to https://console.aws.amazon.com/lambda/home and click Create a lambda function

Step 2

Click on Blank Function (custom)

Step 3

Click on empty (stroked) box and select S3 from combo

Step 4

Select your Bucket (same as for CloudFront distribution)

Step 5

Set an Event Type to "Object Created (All)"

Step 6

Set Prefix and Suffix or leave it empty if you don't know what it is.

Step 7

Check Enable trigger checkbox and click Next

Step 8

Name your function (something like: YourBucketNameS3ToCloudFrontOnCreateAll)

Step 9

Select Python 2.7 (or later) as Runtime

Step 10

Paste following code instead of default python code:

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())
            })

Step 11

Open https://console.aws.amazon.com/cloudfront/home in a new browser tab and copy your CloudFront distribution ID for use in next step.

Step 12

Return to lambda tab and paste your distribution id instead of _YOUR_DISTRIBUTION_ID_ in the Python code. Keep surrounding quotes.

Step 13

Set handler: lambda_function.lambda_handler

Step 14

Click on the role combobox and select Create a custom role. New tab in browser will be opened.

Step 15

Click view policy document, click edit, click OK and replace role definition with following (as is):

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

Step 16

Click allow. This will return you to a lambda. Double check that role name that you just created is selected in the Existing role combobox.

Step 17

Set Memory (MB) to 128 and Timeout to 5 sec.

Step 18

Click Next, then click Create function

Step 19

You are good to go! Now on, each time you will upload/reupload any file to S3, it will be evaluated in all CloudFront Edge locations.

PS - When you are testing, make sure that your browser is loading images from CloudFront, not from local cache.

PSS - Please note, that only first 1000 files invalidation per month are for free, each invalidation over limit cost $0.005 USD. Also additional charges for Lambda function may apply, but it is extremely cheap.

查看更多
Emotional °昔
5楼-- · 2019-01-16 00:38

As of March 19, Amazon now allows Cloudfront's cache TTL to be 0 seconds, thus you (theoretically) should never see stale objects. So if you have your assets in S3, you could simply go to AWS Web Panel => S3 => Edit Properties => Metadata, then set your "Cache-Control" value to "max-age=0".

This is straight from the API documentation:

To control whether CloudFront caches an object and for how long, we recommend that you use the Cache-Control header with the max-age= directive. CloudFront caches the object for the specified number of seconds. (The minimum value is 0 seconds.)

查看更多
Ridiculous、
6楼-- · 2019-01-16 00:39

Bucket Explorer has a UI that makes this pretty easy now. Here's how:

Right click your bucket. Select "Manage Distributions."
Right click your distribution. Select "Get Cloudfront invalidation list" Then select "Create" to create a new invalidation list. Select the files to invalidate, and click "Invalidate." Wait 5-15 minutes.

查看更多
Fickle 薄情
7楼-- · 2019-01-16 00:41

With the Invalidation API, it does get updated in a few of minutes.
Check out PHP Invalidator.

查看更多
登录 后发表回答