
Lors de re:Invent 2018, AWS nous a proposé une nouvelle façon d'utiliser les fonctions Lambda pour alimenter les API ou les sites Web : une intégration avec leur équilibreur de charge d'application Elastic Load Balancing. Auparavant, la méthode de référence pour alimenter une API avec Lambda était avec API Gateway. Quelles sont les différences entre les deux ? Pouvez-vous avoir une fonction Lambda qui fonctionne à la fois pour APIGateway et Application Load Balancer ? Quand faut-il choisir l'un plutôt que l'autre ? Cet article répond à toutes ces questions.
Notez que cet article est une plongée technique approfondie dans les différences entre ces deux technologies. Si vous recherchez davantage l'analyse de rentabilisation entre les deux, veuillez lire cet article :
Économiser de l'argent en remplaçant API Gateway par l'intégration Lambda d'Application Load Balancer
Ou, si vous voulez commencer tout de suite avec des exemples de travail, j'ai fait le travail pour vous et expliqué comment vous pouvez déployer une fonction qui s'exécute à la fois avec API Gateway et Application Load Balancer dans cet article :
Comment configurer l'équilibreur de charge d'application avec Lambda
Comment fonctionne Application Load Balancer par rapport à API Gateway ?
Sur un équilibreur de charge d'application, vous mappez certains chemins (par ex./api/*
) à un "groupe cible". Jusqu'à ce que l'intégration avec Lambda soit annoncée, vous pouviez considérer un groupe cible comme un groupe de ressources - comme les instances EC2 - qui pourraient répondre à la demande. Dans le contexte d'une fonction Lambda, un groupe cible peut avoirunLa fonction Lambda y est associée de sorte que chaque fois que le groupe cible doit répondre à une demande, l'ALB enverra à votre fonction Lambda un objet de demande en tant qu'événement de la fonction, et votre fonction répondra avec un objet de réponse. L'ALB - tout comme API Gateway - gère toutes les interactions HTTP(S) réelles.
API Gateway ne prend en charge que SSL (HTTPS), tandis qu'avec ALB, vous pouvez également prendre en charge HTTP - même si la prise en charge de HTTP devient pratiquement inutile à mesure que l'ensemble du Web poursuit sa transition vers HTTPS uniquement.
Fondamentalement, la façon dont vous écrivez vos fonctions Lambda pour Application Load Balancer et API Gateway est fondamentalement la même. Mais il existe des différences subtiles - et pour la plupart non documentées - entre les deux. Espérons qu'AWS améliore bientôt la documentation de l'intégration ALB/Lambda, mais en attendant, voici les différences que j'ai notées. Si vous voulez vous lancer directement avec quelques exemples, vous pouvez également accéder directement à montutoriel avec des exemples d'utilisation de Lambda avec Application Load Balancer.
Différences de fonctionnalités entre l'équilibreur de charge d'application et la passerelle API
Lorsqu'on lui a demandé quand utiliser API Gateway sur Application Load Balancer, Dougal Ballantyne, le chef de produit pour Amazon API Gateway, a souligné les fonctionnalités d'APIGW qu'ALB n'a pas :
Si vous créez une API et que vous souhaitez tirer parti d'AuthN/Z, demander la validation, la limitation du débit, la génération de SDK, le backend de service AWS direct, utilisez#APIGateway. Si vous souhaitez ajouter Lambda à une application Web existante derrière ALB, vous pouvez maintenant simplement l'ajouter à la route nécessaire.
– Dougal Ballantyne @ MER (@dsballantyne)29 novembre 2018
Et il a raison - APIGW vous offre des fonctionnalités qui ne sont tout simplement pas disponibles dans ALB. Voici des détails sur quelques-uns de ceux qu'il a mentionnés :
- Authentification et autorisation: API Gateway dispose d'unensemble de fonctionnalités entourant auth et auth. Par exemple:
- Authentification basée sur des jetons
- Autorisations basées sur les ressources
- Intégration avec IAM pour contrôler l'accès à l'API
- Autorisateurs personnalisés qui gèrent l'autorisation et définissent les politiques IAM personnalisées avec lesquelles la fonction API s'exécutera
- Mappage des requêtes et des réponses: API Gateway prend en charge l'intégration avec les systèmes hérités en étant capable demapper les requêtes et les réponsesau format requis par le système backend.
- Cela dit, je vois rarement cela nécessaire pour les piles sans serveur, car si vous utilisez APIGW avec Lambda, il s'agit probablement d'un nouveau code - et non d'un code hérité qui nécessite un mappage - et vous pouvez utiliser leIntégration "proxy" API Gatewaypour Lambda.
Mais, vous payez un peu plus cher pour ces fonctionnalités, comme expliqué dans mon article suréconomiser de l'argent en remplaçant API Gateway par Application Load Balancer. Si vous avez besoin d'aide pour choisir entre les deux options, lisez cet article pour une analyse complète.
Détails de la demande/réponse d'événement Lambda pour l'équilibreur de charge d'application
Si vous avez décidé que vous n'avez pas besoin de ces fonctionnalités API Gateway supplémentaires et que vous avez suffisamment de trafic pour qu'un équilibreur de charge d'application ait un sens, vous devez savoir comment écrire votre fonction Lambda pour répondre aux demandes ALB. Pour la plupart, votre fonction fonctionnera exactement comme avec API Gateway - votre fonction Lambda recevra un objet d'événement avec des détails sur la demande, et vous répondrez (ou invoquerez le Lambdacallback) avec un objet représentant un HTTP(S) réponse.
Notez que lorsque je parle des formats d'événement de demande et de réponse pour API Gateway, je suppose que vous utilisez lePasserelle APIintégration proxy, qui est la manière la plus courante d'utiliser API Gateway avec Lambda. Si vous utilisez la coutumefonctionnalités de mappage de réponse du demandeur d'API Gateway, le format de votre événement et de votre objet de réponse dépendra de la façon dont vous avez configuré vos mappages.
Voici les différences que j'ai trouvées dans les objets de demande et de réponse d'intégration de proxy API Gateway par défaut par rapport à ceux d'Application Load Balancer :
Différences de format d'événement de demande d'équilibreur de charge d'application
Comparé à laobjet de requête de l'intégration du proxy API Gateway, l'événement de demande de l'Application Load Balancer qu'il envoie à votre fonction Lambda aura les différences suivantes :
evt.ressource
: Cette propriété n'existe pas sur l'objet de requête ALB car ALB n'a pas la même notion de ressources qu'API Gateway.evt.headers
: Sur APIGW, les en-têtes sont sensibles à la casse, mais sur ALB, les noms d'en-tête que vous obtenez dans l'objet de requête seront tous en minuscules.- Notez également que les points de terminaison API Gateway font toujours partie d'une distribution CloudFront, vous obtenez doncEn-têtes CloudFrontdans votre objet d'en-têtes de requête pour déterminer des éléments tels que le pays à partir duquel l'utilisateur se connecte et le type d'appareil approximatif utilisé par l'utilisateur. Vous n'obtenez pas ces en-têtes avec ALB de manière native (lecteurs d'AWS - considérez cela comme une demande de fonctionnalité pour ALB), mais si vous en avez vraiment besoin, vous pouvez toujours mettre une distribution CloudFront devant votre ALB - ce qui sera toujours plus rentable que d'utiliser API Gateway ne contient que ces en-têtes.
evt.queryStringParameters
: S'il n'y a pas de paramètres de chaîne de requête, APIGW définit ce champ surnul
, alors que l'ALB vous donne un objet vide{}
.- Notez qu'APIGW et ALB sont identiques en ce sens qu'ils envoient les paramètres de chaîne de requête avec le cas exact où ils sont apparus dans l'URL (par opposition aux en-têtes décrits ci-dessus).
- Notez que les clés et les valeurs de
evt.queryStringParameters
sera:- URL déjà décodéepour vous sur API Gateway
- par exemple.
?foo%5Ba%5D=foo%5B
sera{ 'foo[a]': [ 'foo[' ] }
- par exemple.
- maisURL non décodéesur ALB
- par exemple.
?foo%5Ba%5D=foo%5B
sera{ 'foo%5Ba%5D' : [ 'foo%5B' ] }
- par exemple.
- URL déjà décodéepour vous sur API Gateway
evt.multiValueHeaders
: Sur APIGW, vous obtenez automatiquement un champ nommémultiValueHeaders
dans votre objet de requête. Il contient les valeurs d'en-tête dans un format différent qui permet d'envoyer plusieurs en-têtes avec le même nom. Sur ALB, vous pouvez activer cette fonction en activant lelambda.multi_value_headers.enabled
attribut sur le groupe cible ALB.- Pour en savoir plus sur les en-têtes à valeurs multiples avec ALB, consultezleurs fonctions Lambdadocumentation.
- Notez que si vous activez cette fonctionnalité sur les requêtes, votre réponse ne pourra plus simplement utiliser la norme
en-têtes
format - vous devez également répondre avec unmultiValueHeaders
champ au même format que votre demandemultiValueHeaders
. - Semblable à
queryStringParametersQueryStringParameters
, APIGW vous donnenul
et ALB vous donne{}
pour ce champ lorsqu'il n'y a pas d'en-tête.
evt.multiValueQueryStringParameters
: Cela se comporte de la même manière queevt.multiValueQueryStringParameters
, et est contrôlé par le mêmelambda.multi_value_headers.enabled
attribut (ce qui rend la dénomination de cet attribut un peu malheureuse puisque les paramètres de chaîne de requête ne sont pas vraiment des en-têtes).- LeDocuments sur les en-têtes à valeurs multiples ALB/Lambdadonner un exemple de paramètre de chaîne de requête qui apparaît plusieurs fois dans l'URL.
- Semblable à
queryStringParametersQueryStringParameters
, APIGW vous donnenul
et ALB vous donne{}
pour ce champ lorsqu'il n'y a pas de paramètres de chaîne de requête.
evt.requestContext
: Sur APIGW, vous obtenez de nombreuses informations dans le contexte de la demande - des détails sur les ressources API Gateway impliquées dans la demande, ainsi que des informations d'identité si vous utilisez des fonctionnalités d'authentification/autorisation d'APIGW. D'un autre côté, cet objet est très simple sur un ALB, ne vous donnant que l'ARN du groupe cible qui est invoqué.- Remarque : comme indiqué ci-dessous, vous pouvez utiliser la présence de
evt.requestContext.elb
pour déterminer que votre fonction Lambda a été appelée par un équilibreur de charge d'application si votre fonction est configurée pour être utilisée à la fois avec une APIGW et un ALB. Le fait de savoir que la fonction a été invoquée par l'ALB vous permettra d'apporter les modifications subtiles nécessaires à votre format de réponse lorsque vous répondez à la requête.
- Remarque : comme indiqué ci-dessous, vous pouvez utiliser la présence de
evt.pathParameters
: est une construction APIGW uniquement puisque vous mappez des "paramètres de chemin" dans les URL que vous configurez pour APIGW.- Sur ALB, vous ne spécifiez pas de paramètres de chemin - vous spécifiez simplement des modèles d'URL qui correspondent à divers groupes cibles (un groupe cible peut avoir une seule fonction Lambda). Toute autre analyse de l'URL pour en extraire des paramètres devra être effectuée dans votre Fonction lambda.
éventuellement.stageVariables
: est une construction APIGW uniquement, car elle prend en charge le déploiement de plusieurs "étapes" de votre application.
Si vous souhaitez voir un objet de requête dans son intégralité, je vous recommande de déployer les exemples de services que j'ai créés pour vous, comme expliqué dans lecomment configurer ALB avec Lambdaarticle. Dans ces exemples, vous allez déployer un simple service « echo » qui renvoie l'événement d'entrée Lambda, ce qui vous permet de voir facilement les différences exactes entre les deux formats de demande.
Différences de format d'événement de réponse de l'équilibreur de charge d'application
Comparé à laobjet de réponse de l'intégration du proxy API Gateway, l'objet de réponse qu'Application Load Balancer s'attend à ce que votre fonction renvoie (ou transmette à son rappel) présente ces différences :
étatDescription
: Ce champ doit être défini en plus du champ normalstatusCode
. LeétatDescription
est une concaténation du code d'état HTTP (par exemple, 200) et de la "description" de ce code (par exemple, "OK"), avec un espace entre le code et la description.- Par exemple:
200 D'accord
301 Déménagé Définitivement
302 Trouvé
404 Non trouvé
- Important : Pour une raison quelconque, APIGW générera une erreur (répondra par "Erreur de serveur interne") si vous incluez un
étatDescription
champ dans votre réponse pour APIGW.
- Par exemple:
estBase64Encodé
: Ce champ est un booléen qui indique si votre réponse a été encodée en base64 ou non (par exemple, si vous répondiez avec des données binaires, vous l'encoderiez en base64 en premier). Le champ est facultatif sur APIGW, maisrequis sur ALB.en-têtes
: Sur APIGW, il est facultatif de renvoyer les en-têtes, mais sur ALB, vous devez spécifier unen-têtes
champ, même si vous ne le définissez que sur un objet vide{}
.multiValueHeaders
: Comme mentionné ci-dessus, si vous avez activé la fonctionnalité d'en-têtes à valeurs multiples sur le groupe cible associé à votre fonction Lambda, vousdoit également répondre par unmultiValueHeaders
champdans le format qu'il attend.
Voici un exemple complet de réponse que votre fonction Lambda enverrait :
{"code d'état":200,"statutDescription":"200 d'accord","en-têtes": {"Type de contenu":"applications/json"},"multiValueHeaders": {"Type de contenu": ["applications/json"] },"isBase64Encoding":FAUX,"corps":"{\"Bonjour le monde\"}"}
Comment utiliser Lambda avec Application Load Balancer et API Gateway simultanément
Il est possible (et assez simple) d'utiliser la même fonction Lambda derrière API Gateway et un équilibreur de charge d'application. Bien que ce ne soit pas quelque chose que vous fassiez tout le temps, cela peut être très utile pour une stratégie de migration où vous utilisez déjà API Gateway et souhaitez passer à un ALB. Vous pouvez déployer une fonction qui fonctionne derrière les deux pendant cette période intermédiaire où vous exécutez toujours les deux.
Fondamentalement, il y a deux étapes pour que votre fonction fonctionne simultanément dans les deux environnements :
- Ajustez votre code pour gérer les différences dans l'objet de requête de l'événement. La liste ci-dessus devrait vous y aider. Les principales choses à surveiller sont :
- Paramètres de cheminn'existent pas dans ALB, vous pourriez donc en avoir besoin
evt.path
analyse dans votre fonction. - Noms des en-têtessont tous en minuscules dans ALB, assurez-vous donc que vous effectuez une recherche insensible à la casse dans l'objet d'en-têtes lors de la récupération des en-têtes de requête.
- Paramètres de cheminn'existent pas dans ALB, vous pourriez donc en avoir besoin
- Ajustez votre format de réponse pour ALB lorsque la demande provient d'ALB. Malheureusement, il n'y a pas "d'objet de réponse unique" en raison des différences mineures entre APIGW et ALB - en particulier le problème mentionné ci-dessus avec
étatDescription
.- Ainsi, vous devrez détecter si la requête provient d'un ALB (en recherchant la présence du
evt.requestContext.elb
champ), et si la demande provient d'un ALB, ajoutez leétatDescription
champ, assurez-vous que leen-têtes
etestBase64Encodé
champs sont là, et - si vous recevez des en-têtes à plusieurs valeurs, assurez-vous d'inclure vos en-têtes de réponse dans le même format quemultiValueHeaders
.
- Ainsi, vous devrez détecter si la requête provient d'un ALB (en recherchant la présence du
Voici un exemple complet (et simple) de réponse aux requêtes APIGW et ALB à partir de la même fonction :
'utiliser strictement';module.exportations.écho = fonction(evt,contexte,cb) {était resp;// À quoi cela ressemblerait pour API Gateway resp ={statusCode: 200,en-têtes:{'Type de contenu': 'application/json'},corps: JSON.stringifier({Bonjour: "monde"}), } ;// Mais si votre fonction est invoquée par ALB, vous devez également le faire : si(evt.requestContext && evt.requestContext.coude) {resp.étatDescription = '200 d'accord';resp.estBase64Encodé = FAUX;// De même, si l'ALB est configuré pour vous envoyer des en-têtes à valeurs multiples pour le // demande, alors vous devez également répondre avec des en-têtes à plusieurs valeurs, nous faisons donc cela // fonction de carte simple. si(evt.multiValueHeaders) {resp.multiValueHeaders =Objet.clés(resp.en-têtes).réduire((note,k) => {note[k]=[resp.en-têtes[k] ] ;retour note; }, {}); } }cb(nul,resp);};
Conclusion
Si vous voulez essayer tout cela par vous-même, j'ai déjà fait le travail pour vous. Je vous recommande vivement de lire l'article suivant de cette série qui vous donne des exemples que vous pouvez déployer et exécuter en quelques minutes afin que vous puissiez expérimenter l'exécution simultanée d'une fonction Lambda derrière API Gateway et Application Load Balancer. Vérifiez-le.
Comment configurer l'équilibreur de charge d'application avec Lambda
Y a-t-il d'autres différences entre APIGW et ALB que vous avez trouvées dans votre expérimentation ? Ou cet article vous a-t-il aidé à créer quelque chose de cool ? S'il vous plaît, laissez un commentaire ci-dessous!
Rester informé
Abonnez-vous à laServir sans serveurnewsletter ou suivez-moi sur Twitter. Je vous tiendrai au courant du monde sans serveur, des nouvelles ressources de formation etJe ne vendrai ni ne partagerai jamais vos coordonnées.