Erzwingen Sie die CloudFront-Verteilung / Dateiaktualisierung


146

Ich verwende CloudFront von Amazon, um statische Dateien meiner Webanwendungen bereitzustellen.

Gibt es keine Möglichkeit, einer Cloudfront-Distribution mitzuteilen, dass sie ihre Datei aktualisieren muss, oder auf eine einzelne Datei hinzuweisen, die aktualisiert werden soll?

Amazon empfiehlt, dass Sie Ihre Dateien wie logo_1.gif, logo_2.gif usw. versionieren, um dieses Problem zu umgehen. Dies scheint jedoch eine ziemlich dumme Lösung zu sein. Gibt es absolut keinen anderen Weg?



Als Nebenbemerkung halte ich es nicht für dumm, solche statischen Dateien zu benennen. Wir haben es oft benutzt und das automatische Umbenennen gemäß Dateiversion in der Versionskontrolle hat uns viele Kopfschmerzen erspart.
Eis

1
@eis, es sei denn, die Datei, die Sie ersetzen müssen, wurde mit 1000 verschiedenen Stellen online verknüpft. Viel Glück beim Aktualisieren all dieser Links.
Jake Wilson

@ Jakobud warum sollten die Links in diesem Fall aktualisiert werden? Sie beziehen sich auf eine bestimmte Version, die nicht die neueste ist, wenn die Datei geändert wurde. Wenn die Datei nicht geändert wurde, funktioniert sie wie zuvor.
Eis

6
In einigen Fällen kann ein Unternehmen einen Fehler machen, wenn es das falsche Bild für etwas oder eine andere Art von Artikel veröffentlicht, wenn es von einer Anwaltskanzlei eine Abnahmemitteilung erhält und die Datei ersetzen muss. Das einfache Hochladen einer neuen Datei mit einem neuen Namen wird diese Art von Problem nicht beheben, was heutzutage leider immer häufiger vorkommt.
Jake Wilson

Antworten:


134

Gute Nachrichten. Amazon hat endlich eine Invalidierungsfunktion hinzugefügt. Siehe die API-Referenz .

Dies ist eine Beispielanforderung aus der API-Referenz:

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
Bitte beachten Sie, dass die Ungültigmachung einige Zeit in Anspruch nehmen wird (laut einigen von mir gelesenen Blog-Posts anscheinend 5 bis 30 Minuten).
Michael Warkentin

37
Wenn Sie selbst keine API-Anfrage stellen möchten, können Sie sich auch bei der Amazon Console anmelden und dort eine Invalidierungsanfrage erstellen: docs.amazonwebservices.com/AmazonCloudFront/latest/…
j0nes

Wie lange dauert es ungefähr, bis die Invalidierung wirksam wird, wenn Sie die API verwenden, um die Ungültigmachung durchzuführen?
ill_always_be_a_warriors

20
Denken Sie daran, dass dies nach Ihren ersten 1.000 Ungültigkeitsanfragen pro Monat 0,005 USD pro Datei kostet. Aws.amazon.com/cloudfront/pricing
TimS

1
@MichaelWarkentin Nachdem createInvalidationich eine API- Anfrage gestellt habe, dauert es ungefähr 5-10 Minuten, bis das Update ungültig wird. Beachten Sie, dass ich diesen Kommentar 4 Jahre nach Ihrem schreibe .
Tim Peterson

19

Ab dem 19. März erlaubt Amazon jetzt, dass die Cache-TTL von Cloudfront 0 Sekunden beträgt. Daher sollten Sie (theoretisch) niemals veraltete Objekte sehen. Wenn Sie also Ihre Assets in S3 haben, können Sie einfach zu AWS Web Panel => S3 => Eigenschaften bearbeiten => Metadaten wechseln und dann Ihren Wert für "Cache-Control" auf "max-age = 0" setzen.

Dies geht direkt aus der API-Dokumentation hervor :

Um zu steuern, ob und wie lange CloudFront ein Objekt zwischenspeichert, empfehlen wir, den Cache-Control-Header mit der Direktive max-age = zu verwenden. CloudFront speichert das Objekt für die angegebene Anzahl von Sekunden zwischen. (Der Mindestwert beträgt 0 Sekunden.)


Wo befindet sich diese Einstellung in der neuen AWS Console-Benutzeroberfläche? Ich kann es nicht finden.
ill_always_be_a_warriors

1
Ich habe die Einstellung für eine einzelne Datei gefunden, aber gibt es eine Einstellung, die dafür sorgt, dass alles, was in meinen Bucket hochgeladen wird, eine TTL von 0 hat?
ill_always_be_a_warriors

Obwohl ich definitiv auch an einer eimerweiten Einstellung interessiert wäre, fand ich dies eine schnellere / bessere Lösung. Invalidierungsanfragen (zusammen mit dem Rest der API) sind sehr verwirrend und schlecht dokumentiert, und ich habe meine Räder 3 Stunden lang gedreht, bevor dies sofort funktionierte.
Zwei-Bit-Alchemist

33
Nennen Sie mich verrückt, aber wenn Sie die TTL auf 0 und das maximale Alter auf 0 setzen, wird CloudFront wirklich ohne Caching verwendet. Würde das nicht alle Anfragen an den Ursprung weiterleiten, der ständig nach Updates sucht? Das CDN im Wesentlichen unbrauchbar machen?
Acidjazz

6
Wenn Sie Cloudfront nur als Mechanismus für eine statische SSL-fähige S3-Site mit einer benutzerdefinierten Domäne verwenden, spielt das Caching keine Rolle. Wir diskutieren auch, dass in Entwicklungsphasen 0-maliges Caching gut ist.
Dan G

10

Mit der Invalidierungs-API wird sie in wenigen Minuten aktualisiert.
Schauen Sie sich PHP Invalidator an .


Genau das habe ich gesucht. Ich werde dies in Beanstalkapps Web-Hooks einbinden, wenn ich es automatisch von Git aus bereitstelle! Danke für den Link!
Cointilt

10

Automatisches Update-Setup in 5 Minuten

Okay Leute. Die derzeit beste Möglichkeit, ein automatisches CloudFront-Update (Ungültigmachung) durchzuführen, besteht darin, eine Lambda-Funktion zu erstellen, die jedes Mal ausgelöst wird, wenn eine Datei in den S3-Bucket hochgeladen wird (eine neue oder neu geschriebene).

Selbst wenn Sie noch nie zuvor Lambda-Funktionen verwendet haben, ist dies ganz einfach. Befolgen Sie einfach meine Schritt-für-Schritt-Anweisungen, und es dauert nur 5 Minuten:

Schritt 1

Gehen Sie zu https://console.aws.amazon.com/lambda/home und klicken Sie auf Lambda-Funktion erstellen

Schritt 2

Klicken Sie auf Leere Funktion (benutzerdefiniert)

Schritt 3

Klicken Sie auf das leere Feld und streichen Sie S3 aus der Kombination

Schritt 4

Wählen Sie Ihren Bucket aus (wie bei der CloudFront-Distribution).

Schritt 5

Setzen Sie einen Ereignistyp auf "Objekt erstellt (alle)".

Schritt 6

Stellen Sie Präfix und Suffix ein oder lassen Sie es leer, wenn Sie nicht wissen, was es ist.

Schritt 7

Überprüfen Sie Trigger aktivieren Checkbox und klicken Sie auf Weiter

Schritt 8

Benennen Sie Ihre Funktion (etwa: YourBucketNameS3ToCloudFrontOnCreateAll )

Schritt 9

Wählen Sie Python 2.7 (oder höher) als Laufzeit aus

Schritt 10

Fügen Sie anstelle des Standard-Python-Codes folgenden Code ein:

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

Schritt 11

Öffnen Sie https://console.aws.amazon.com/cloudfront/home in einem neuen Browser-Tab und kopieren Sie Ihre CloudFront-Verteilungs-ID, um sie im nächsten Schritt zu verwenden.

Schritt 12

Kehren Sie zur Registerkarte Lambda zurück und fügen Sie Ihre Verteilungs-ID anstelle von _YOUR_DISTRIBUTION_ID_ in den Python-Code ein. Halten Sie umgebende Anführungszeichen.

Schritt 13

Set - Handler : lambda_function.lambda_handler

Schritt 14

Klicken Sie auf die Rolle Combobox und wählen Sie eine benutzerdefinierte Rolle erstellen . Der neue Tab im Browser wird geöffnet.

Schritt 15

Klicken Sie auf Richtliniendokument anzeigen , klicken Sie auf Bearbeiten , klicken Sie auf OK und ersetzen Sie die Rollendefinition durch Folgendes (wie sie ist):

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

Schritt 16

Klicken Sie auf Zulassen . Dies bringt Sie zu einem Lambda zurück. Überprüfen Sie, ob der soeben erstellte Rollenname in der vorhandenen Rolle ausgewählt ist Combobox " .

Schritt 17

Stellen Sie den Speicher (MB) auf 128 und das Zeitlimit auf 5 Sekunden ein.

Schritt 18

Klicken Sie auf Weiter und dann auf Funktion erstellen

Schritt 19

Du bist startklar! Jedes Mal, wenn Sie eine Datei in S3 hochladen / erneut hochladen, wird sie an allen CloudFront Edge-Speicherorten ausgewertet.

PS - Stellen Sie beim Testen sicher, dass Ihr Browser Bilder aus CloudFront und nicht aus dem lokalen Cache lädt.

PSS - Bitte beachten Sie, dass nur die ersten 1000 Ungültigmachungen von Dateien pro Monat kostenlos sind. Jede Ungültigmachung über das Limit hinaus kostet 0,005 USD. Es können auch zusätzliche Gebühren für die Lambda-Funktion anfallen, diese sind jedoch äußerst günstig.


Nur der letzte Artikel aus jeder S3-Charge?
Phil

@Phil Der Code ist so geschrieben, dass nur neu hochgeladene Dateien ungültig werden, nicht ein ganzer Bucket. Beim Hochladen mehrerer Dateien wird jede Datei separat ungültig. Klappt wunderbar.
Kainax

Der einzige Grund, warum dieser Code wie erwartet funktioniert, ist, dass S3 derzeit nur ein Element pro Benachrichtigung enthält, dh die Länge des Arrays beträgt glücklicherweise immer 1, und folglich erhalten Sie eine völlig neue Benachrichtigung, selbst wenn Sie mehrere Dateien auf einmal hochladen pro Datei. Sie erhalten auf keinen Fall eine Benachrichtigung für den gesamten Bucket. Trotzdem ist dieser geschriebene Code nicht bereit, sollte AWS dieses Verhalten ändern. Es ist weitaus sicherer, Code zu schreiben, der das gesamte Array unabhängig von der Länge verarbeitet. Dies war mein ursprünglicher (leider übersehener) Punkt.
Phil

Der einzige Grund, warum AWS Ereignishandler hinzufügt, ist ... nun ... die Behandlung von Ereignissen. Warum sollten sie es entfernen? Unabhängig davon, wie eine neue Datei hinzugefügt wurde, sollte sie ein Ereignis für die API auslösen. So funktioniert es jetzt und funktioniert auch weiterhin. Ich benutze AWS seit 4 Jahren und sie haben nie etwas geändert, sodass der vorherige Code nicht mehr funktioniert. Selbst wenn sie die API ändern, ändern sie sie in eine neue eigenständige Version, aber alle vorherigen Versionen werden immer unterstützt. In diesem speziellen Fall glaube ich einfach nicht, dass das Ereignis einer persönlichen Datei jemals entfernt wird. Es wird wahrscheinlich bereits von Millionen Projekten weltweit verwendet.
Kainax

Falls ich Ihren ersten Kommentar falsch verstehe und Sie meinen, dass 'Menge': 1 nur den letzten Artikel hinzufügt, gibt es für jeden Artikel im Array eine FOR-Schleife.
Kainax

9

Bucket Explorer hat eine Benutzeroberfläche, die dies jetzt ziemlich einfach macht. Hier ist wie:

Klicken Sie mit der rechten Maustaste auf Ihren Eimer. Wählen Sie "Verteilungen verwalten".
Klicken Sie mit der rechten Maustaste auf Ihre Distribution. Wählen Sie "Cloudfront-Ungültigkeitsliste abrufen" und anschließend "Erstellen", um eine neue Ungültigkeitsliste zu erstellen. Wählen Sie die zu ungültig machenden Dateien aus und klicken Sie auf "Ungültig machen". Warten Sie 5-15 Minuten.


4

Wenn Sie boto installiert haben (das nicht nur für Python ist, sondern auch eine Reihe nützlicher Befehlszeilenprogramme installiert), bietet es ein Befehlszeilenprogramm, das speziell als cfadmin"Cloud Front Admin" bezeichnet wird und die folgenden Funktionen bietet:

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

Sie machen Dinge ungültig, indem Sie Folgendes ausführen:

$sam# cfadmin invalidate <distribution> <path>

Tatsächlich ist cfadmin ein sehr hilfreiches Tool, insbesondere wenn Sie den CloudFront-Cache über das Bereitstellungsskript console \ bash \ travis ci zurücksetzen müssen. Übrigens hier ist der Beitrag, wie man den CoudFront-Cache während der Travis-Bereitstellung auf aws zurücksetzt \ ungültig macht
Mikita Manko

3

Posten Sie einfach, um alle Besucher dieser Seite (erstes Ergebnis bei 'Cloudfront File Refresh') darüber zu informieren, dass es einen benutzerfreundlichen + Zugriff gibt benutzerfreundlicher Online-Invalidator verfügbar ist

Dieser neue Ungültigmacher ist:

  • Vollständig online (keine Installation)
  • 24x7 verfügbar (von Google gehostet) und erfordert keine Mitgliedschaft.
  • Es gibt Verlaufsunterstützung und Pfadprüfung, damit Sie Ihre Dateien problemlos ungültig machen können. (Oft mit nur wenigen Klicks nach der ersten Ungültigmachung!)
  • Es ist auch sehr sicher, wie Sie beim Lesen des Veröffentlichungsbeitrags erfahren werden .

Vollständige Offenlegung: Ich habe dies gemacht. Habe Spaß!


2
Entschuldigung, aber selbst wenn Sie sagen, dass die Anmeldeinformationen nicht gespeichert oder ausgelaugt sind, sollten Sie diese niemals an Dritte weitergeben. Kann eine Remote-Amazon-Authentifizierung oder so etwas implementieren?
d.raev

Sie sollten dies mindestens hinter https setzen.
Oliver Tynes

Online-Tools sind im Allgemeinen nett, aber die Angabe von Anmeldeinformationen für Tools von Drittanbietern ist ein gültiges Sicherheitsbedenken. Ich würde vorschlagen, entweder die offizielle Webkonsole oder das offizielle CLI-Tool zu verwenden .
RayLuo

2
Für die Sicherheit anderer stimme ich diese Antwort ab. Sie sollten niemals Leute nach ihren Anmeldeinformationen fragen
Moataz Elmasry

3

Eine sehr einfache Möglichkeit ist die FOLDER-Versionierung.

Wenn Ihre statischen Dateien beispielsweise Hunderte sind, legen Sie sie einfach alle in einem Ordner ab, der nach Jahr + Versionierung aufgerufen wird.

Zum Beispiel benutze ich einen Ordner namens 2014_v1, in dem ich alle meine statischen Dateien habe ...

Also habe ich in meinem HTML immer den Verweis auf den Ordner eingefügt. (Natürlich habe ich ein PHP-Include, in dem ich den Namen des Ordners festgelegt habe.) Wenn ich also eine Datei ändere, ändert sich tatsächlich alles in meinen PHP-Dateien.

Wenn ich eine vollständige Aktualisierung möchte, benenne ich den Ordner einfach in 2014_v2 in meine Quelle um und ändere ihn innerhalb des PHP-Includes in 2014_v2

Der gesamte HTML-Code ändert sich automatisch und fragt den neuen Pfad, den Cloudfront-MISS-Cache und fordert ihn bei der Quelle an.

Beispiel: SOURCE.mydomain.com ist meine Quelle, cloudfront.mydomain.com ist CNAME für die Cloudfront-Verteilung.

Das PHP hat diese Datei cloudfront.mydomain.com/2014_v1/javascript.js genannt. Wenn ich eine vollständige Aktualisierung möchte, benenne ich den Ordner einfach in "2014_v2" um und ändere das PHP-Include, indem ich den Ordner auf "2014_v2" setze. .

So gibt es keine Verzögerung für die Ungültigmachung und keine Kosten!

Dies ist mein erster Beitrag in stackoverflow, hoffe ich habe es gut gemacht!



2

In Rubin mit dem Nebelstein

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

Selbst bei einer Ungültigmachung dauert es noch 5-10 Minuten, bis die Ungültigmachung auf allen Amazon Edge-Servern verarbeitet und aktualisiert wurde


Du hast gerade mein Leben gerettet!
Fábio Batista

2

Die aktuelle AWS CLI unterstützt die Ungültigmachung im Vorschaumodus. Führen Sie in Ihrer Konsole einmal Folgendes aus:

aws configure set preview.cloudfront true

Ich stelle mein Webprojekt mit npm bereit. Ich habe die folgenden Skripte in meinem 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"
}

Mit den oben genannten Skripten können Sie Ihre Site bereitstellen mit:

npm run deploy

1
Ich denke, Sie brauchen das Sternchen in Ihrem Befehl 'aws.invalidate', wechseln Sie --paths /zu --paths /*. meins war auch wie deins und es hat die Verteilung nicht ungültig gemacht ...
Herald Smit

1

Wenn Sie AWS verwenden, verwenden Sie wahrscheinlich auch das offizielle CLI-Tool (früher oder später). AWS CLI Version 1.9.12 oder höher unterstützt das Ungültigmachen einer Liste von Dateinamen.

Vollständige Offenlegung: Ich habe dies gemacht. Habe Spaß!


Toter Link - führt zu einem 404 :( und ich kann ihn nicht aktualisieren, da Version 1.9.12 in den Versionshinweisen fehlt ( aws.amazon.com/releasenotes/?tag=releasenotes%23keywords%23cli )
SlyDave

Alter, das war eine Version, die vor fast 3 Jahren veröffentlicht wurde. Probieren Sie die neueste Version aus und die Funktion ist wahrscheinlich noch vorhanden. (Vollständige Offenlegung: Ich arbeite nicht mehr an AWS CLI.)
RayLuo

Oh, ich weiß, fand es nur seltsam, dass von allen Releasenotes nur 1.9.12 nicht existiert: D (was ich damit meinte, dass ich den Link nicht aktualisieren konnte). Der Kommentar war eher ein Hinweis für jeden, der hier den Weg gefunden hat, wie ich es tat und die Releasenotes für AWS CLI finden musste. Kein Schaden, kein Foul.
SlyDave

0

Gehen Sie zu CloudFront.

Klicken Sie auf Ihre ID / Distributionen.

Klicken Sie auf Invalidierungen.

Klicken Sie auf Invalidierung erstellen.

Geben Sie im riesigen Beispielfeld * ein und klicken Sie auf Ungültig machen

Getan

Geben Sie hier die Bildbeschreibung ein

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.