15

TLDR: Nous devons tromper CloudFront 307 rediriger la mise en cache en créant un nouveau comportement de cache pour les réponses à venir de notre fonction Lambda.Redimensionner les images à la volée dans CloudFront et les obtenir instantanément dans la même URL: AWS CloudFront -> S3 -> Lambda -> CloudFront

Vous ne croirez pas à quel point nous sommes proches pour y parvenir. Nous avons tellement mal pris dans la dernière étape.

cas d'affaires:

Nos magasins d'application des images dans S3 et les sert avec CloudFront afin d'éviter les ralentissements géographiques à travers le monde. Maintenant, nous voulons être très flexibles avec la conception et pouvoir demander de nouvelles dimensions d'image directement dans l'URL CouldFront! Chaque nouvelle taille d'image sera créée à la demande puis stockée dans S3, donc la seconde fois qu'elle sera demandée, elle sera servie très rapidement car elle existera dans S3 et sera également mise en cache dans CloudFront.

Supposons que l'utilisateur ait téléchargé l'image chucknorris.jpg. Seule l'image originale sera stockée dans S3 et wil être servi sur notre page comme ceci:

//xxxxx.cloudfront.net/chucknorris.jpg

Nous avons calculé que nous devons maintenant afficher une miniature de 200x200 pixels. Par conséquent nous avons mis le src d'image dans notre modèle:

//xxxxx.cloudfront.net/chucknorris-200x200.jpg

Lorsque cette nouvelle taille est demandée, les services Web amazon doivent fournir sur la mouche dans le même seau et avec la clé demandée. De cette façon, l'image sera directement chargée dans la même URL de CloudFront.

J'ai fait un dessin laid avec la vue d'ensemble de l'architecture et le flux de travail sur la façon dont nous faisons cela dans AWS:

enter image description here

Voici comment se termine Python Lambda:

return { 
    'statusCode': '301', 
    'headers': {'location': redirect_url}, 
    'body': '' 
} 

Le problème :

Si nous faisons rediriger la fonction Lambda vers S3, cela fonctionne comme un charme. Si nous redirigeons vers CloudFront, il passe en boucle de redirection car CloudFront met en cache 307 (ainsi que 301, 302 et 303). Dès que notre fonction Lambda réoriente à CloudFront, CloudFront appelle l'URL Getaway API au lieu d'aller chercher l'image de S3:

enter image description here

Je voudrais créer un nouveau comportement de cache dans Behaviors paramètres CloudFront onglet. Ce comportement ne doit pas mettre en cache les réponses de Lambda ou S3 (ne sait pas ce qui s'y passe en interne), mais doit toujours mettre en cache les requêtes suivies dans cette même image redimensionnée. J'essaie de définir le modèle de chemin -\d+x\d+\..+$, ajouter l'ARN de la fonction Lambda en ajoutant "Lambda Function Association" et définir le type d'événement Origin Response. À côté de cela, je définis le "Default TTL" à 0.

Mais je ne peux pas enregistrer le comportement en raison d'une erreur:

enter image description here

Sommes-nous sur la bonne voie, ou est l'idée de cette « Lambda Fonction Association » totalement différent?

+0

Vous devez contacter le support AWS concernant ce message d'erreur. Aussi, avez-vous regardé la nouvelle fonctionnalité Lambda @ Edge de Cloudfront? –

Répondre

7

Finalement, j'ai été capable de le résoudre. Bien que ce ne soit pas vraiment une solution structurelle, elle fait ce dont nous avons besoin. D'abord, grâce à la réponse de Michael, j'ai utilisé des modèles de chemins pour faire correspondre tous les types de médias. Deuxièmement, la page Cache Behavior était un peu trompeuse: en effet l'association Lambda est pour Lambda @ Edge, bien que je ne l'aie vu nulle part dans toutes les info-bulles du comportement du cache: tout ce que vous voyez est juste Lambda. Cette fonctionnalité ne peut pas nous aider car nous ne souhaitons pas étendre notre étendue de service AWS avec Lambda @ Edge à cause de ce problème particulier.

Voici l'approche de la solution:
J'ai défini les comportements de cache multiples, un par type de média que nous soutenons:

enter image description here

Pour chaque comportement du cache, je mis le Default TTL être 0.

Et la partie la plus importante: Dans la fonction Lambda, j'ai ajouté un en-tête Cache-Control aux images redimensionnées lors de leur mise en S3:

s3_resource.Bucket(BUCKET).put_object(Key=new_key, 
             Body=edited_image_obj, 
             CacheControl='max-age=12312312', 
             ContentType=content_type) 

Pour vérifier que tout fonctionne, je vois maintenant que la nouvelle l'image dimention est servi avec l'en-tête de cache CloudFront:

enter image description here

+0

Pourquoi est-il si important d'ajouter l'en-tête 'Cache-Control' aux images de redimensionnement? Il me semble qu'en réglant 'Default TTL' sur' 0', c'est déjà suffisant. Non? –

+2

Pour répondre à ma propre question stupide. J'ai lu un autre billet sur ce https://sketchboard.io/blog/serverless-image-resize-with-amazon-lambda qui explique pourquoi le 'max-age' est nécessaire. Il sera utilisé par CloudFront pour déterminer la durée de mise en cache de l'objet (après la première exécution, qui utilise le 0 par défaut). Excellente question et réponse ici! @katericata. –

1

Vous êtes sur la bonne voie ... peut-être ... mais il y a au moins deux problèmes.

La "Lambda Function Association" que vous configurez ici s'appelle Lambda @ Edge et n'est pas encore disponible. Les seuls utilisateurs qui peuvent y accéder sont les utilisateurs qui ont demandé à être inclus dans l'aperçu limité. L'erreur "maximum allowed is 0" signifie que vous n'êtes pas un participant de prévisualisation. Je n'ai vu aucune annonce liée à quand ce sera en direct pour tous les comptes. Mais même une fois qu'il est disponible, il ne va pas vous aider, ici, comme vous le souhaitez, car je ne crois pas qu'un déclencheur de réponse d'origine vous permette de faire quoi que ce soit pour que CloudFront tente un autre destination et suivez la redirection. Si vous voyez une documentation qui contredit cette affirmation, veuillez la porter à mon attention. Cependant, Lambda @ Edge sera utile pour configurer Cache-Control: no-cache sur le 307 afin CloudFront ne le mettra pas en cache, mais la redirection elle-même devra encore aller jusqu'au navigateur. Notez également que Lambda @ Edge ne prend en charge que Node, pas Python ... donc peut-être que cela ne fait même pas partie de votre plan. Je ne peux pas vraiment dire, de la question.

Read about the [email protected] limited preview.

Le deuxième problème:

I am trying to set path pattern -\d+x\d+\..+$

Vous ne pouvez pas faire cela. Les modèles de chemin sont des correspondances de chaînes prenant en charge les caractères génériques *. Ce ne sont pas des expressions régulières. Vous pourriez vous en sortir avec /*-*x*.jpg, cependant, depuis multiple wildcards appear to be supported.

+0

Merci pour toutes les clarifications. J'ai modifié le modèle de chemin que vous avez proposé et j'ai fourni plusieurs comportements pour tous les types de fichiers multimédias. En ce qui concerne Lambda @ Edge, c'est totalement injuste de la part d'Amazon de le définir ainsi. Ils ne mentionnent jamais le mot "Edge" dans la boîte de dialogue Info-bulle. Je ne pense pas que Lambda @ Edge conviendra à nos besoins, d'ailleurs qu'à l'heure actuelle il n'y a que Node, mais nous voulons rester avec Python car nous avons nos algorithmes de recadrage/redimensionnement en utilisant PIL. – katericata

+0

Je ne comprends pas ce que vous voulez dire en l'appelant «injuste». Vous pouvez utiliser une fonction Lambda dans n'importe quelle langue avec API Gateway derrière CloudFront, mais vous ne pouvez que "hooker" et modifier le comportement de demande/réponse CloudFront avec Lambda @ Edge ... et cela (avec le fait que Node.js est le langage supporté) est clairement indiqué dans la [documentation Lambda] (http://docs.aws.amazon.com/lambda/latest/dg/lambda-edge.html) et la [documentation CloudFront] (http: // docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/lambda-at-the-edge.html). AWS n'a pas été trompeur, ici. –

+0

Je suis d'accord avec vous que la documentation officielle indique clairement, cependant, ce que je voulais dire avec ma déclaration était que ce n'est pas indiqué sur la page Cache Behavior (également pas dans le message d'exception). Là, vous ne voyez pas le mot Edge mentionné nulle part, et j'ai trouvé cela un peu trompeur. Dans notre cas, puisque nous n'utilisons que Lambda, cela a été surprenant car Lambda @ Edge est un nouveau service dans la famille AWS et il n'est actuellement pas dans notre champ d'application. :) – katericata