Si vous développez actuellement ou cherchez à commencer à développer des applications sur la pile sans serveur AWS, je pense que vous trouverez cet article intéressant et utile.
Plus tôt cette année, j’ai publié un article sur DZone décrivant mon parcours de l’architecture cloud à l’ingénierie de la fiabilité du cloud. Ce voyage a commencé avec un POC Python Flask et s’est terminé avec une application sans serveur AWS à part entière. J’ai également développé un pipeline DevOps avec GitHub, CodeBuild, Terraform Enterprise et un pipeline d’observabilité avec CloudWatch, PagerDuty et ServiceNow.
Scripter l’ensemble de la pile technologique AWS avec l’infrastructure en tant que code (IaC) – HashiCorp Terraform était cool. Créer une pile d’applications entièrement fonctionnelle dans les environnements SDLC en 10 minutes, c’était encore plus cool.
La conception initiale décrite dans l’article précédent comprenait une API CRUD pour les données du profil d’investissement client (CIP) à l’aide d’AWS Serverless Stack. La charge utile CIP JSON contenait les métadonnées de l’enregistrement et un document de proposition binaire. La taille de la charge utile du message a été initialement estimée à environ 4 Mo. Étant donné qu’AWS API Gateway et Lambda prennent en charge cette taille de charge utile, j’ai décidé de concevoir cette API REST pour l’ingestion de données synchrone. Cette conception a considérablement simplifié la gestion des erreurs en temps réel.
Voici l’architecture simplifiée et elle est réduite au contexte pertinent.
État actuel
Cette solution a très bien fonctionné jusqu’à la fin de l’UAT, lorsque la taille de la charge utile a soudainement dépassé 6 Mo. Les passerelles API ont renvoyé le message d’erreur suivant avec le code d’erreur 413 :
{
"message": "Request Too Long"
}
Une solution potentielle consistait à abandonner la conception sans serveur et à revenir au microservice Flask déployé sur EC2 ou ECS. Bien que cette option n’ait pas entraîné de refonte significative de la réingénierie, son inconvénient majeur était de compromettre les objectifs initiaux de conception sans serveur, de réglage des performances, d’évolutivité élastique et de coût optimal pour chaque fonction Lambda en fonction de l’utilisation. J’ai cherché une autre solution pour ingérer une grande charge utile d’API tout en laissant intact le reste de l’architecture de l’application.
État cible
Voici l’esquisse de la solution, construite au-dessus de l’architecture précédente, également simplifiée pour cet article :
- L’application SaaS appelle un proxy d’API externe.
- Le proxy d’API externe appelle l’API existante si la taille de la charge utile est inférieure à 5 Mo et la nouvelle API pour une taille de charge utile plus importante.
- Les deux API sont privées et accessibles via un point de terminaison VPC.
Passons en revue la nouvelle conception de l’API qui peut ingérer une charge utile de message importante :
4. Le backend de l’API est le service S3. L’API appelle le PutObject
pour stocker la charge utile JSON dans un compartiment S3.
5. Le compartiment S3 déclenche SQS sur le PutObject
un événement.
6. Lambda « interroge longuement » la file d’attente SQS.
7. Une fois déclenchée, la fonction Lambda récupère la charge utile JSON du compartiment S3.
8. La fonction Lambda exécute la même logique que l’autre fonction Lambda déclenchée par la passerelle API. Il était logique de déployer la même base de code pour les deux fonctions Lambda afin d’éviter la duplication de code.
Base de code
Dans la suite de cet article, je vous expliquerai les étapes de création de la passerelle API proxy pour stocker des documents dans S3 sans une seule ligne de code.
La première étape consiste à ajouter un type de média binaire à votre paramètre API afin que la passerelle API puisse encoder et décoder la charge utile du message en fonction de l’en-tête HTTP Content-Type.
L’AWS API Gateway menace une route d’API en tant que ressource ou composition de plusieurs ressources. J’ai créé une ressource statique appelée les propositions, un paramètre de chemin en tant que ressource dynamique appelée Objet, et la méthode POST HTTP.
Dans Demande de méthode, J’ai déclaré le paramètre de chemin appelé Objet et l’en-tête Type de contenu. Considérez-le comme la section de déclaration de variable à référencer plus tard.
Demande de méthode
Les Demande d’intégration section est l’endroit où j’ai configuré l’intégration backend. Dans ce cas, le backend est un autre service AWS S3. J’ai fourni le nom du compartiment S3 et le rôle d’exécution.
Détail important : Le « clé » Le paramètre de chemin référencé dans l’écrasement du chemin est mappé sur le « Objet » paramètre de chemin défini dans le Demande de méthode section. L’en-tête Content-Type nécessaire à l’intégration S3 est mappé sur le même en-tête d’API.
Demande d’intégration
Au moment où j’écris cet article, j’ai découvert que le rôle n’a pas d’autorisation d’écriture de compartiment S3 explicite, mais que la stratégie d’accès au compartiment S3 doit déclarer explicitement l’autorisation S3:PutObject.
Politique d’accès au bucket
Une fois l’API développée et testée, j’avais une autre tâche de recréer cette API dans plusieurs environnements SDLC. Faire ce travail manuellement et à plusieurs reprises serait un effort fastidieux et sujet aux erreurs.
Au début de cet article, j’ai mentionné HashiCorp Terraform en tant que fournisseur IaC. Il existe un module de ressources Terraform pour créer une passerelle API AWS, lié ici.
Ressource Terraform API REST
Ce module est simple à comprendre et à suivre. J’ai trouvé que déclarer manuellement chaque ressource, méthode et intégration pour chaque route API serait un effort laborieux pour s’assurer que toutes les dépendances de module sont correctement référencées. Heureusement, Terraform offre un autre moyen de déclarer l’API REST avec la spécification OpenAPI. Vous pouvez exporter le JSON OpenAPI à partir de la section API Stage existante et l’inclure dans le module API REST Terraform comme suit :
- Inclure OpenAPI dans la ressource API Terraform
Assurez-vous d’externaliser toutes les dépendances spécifiques aux comptes SDLC et AWS, telles que les rôles, les compartiments et les points de terminaison VPC, vers les variables et les sources de données Terraform.
Exécutez les commandes suivantes :
terraform init
terraform fmt
terraform validate
Vous devez exécuter les commandes suivantes si vous n’utilisez pas Terraform Enterprise :
terraform plan
terraform apply
Vous êtes maintenant prêt à valider votre API.
Exécutez la requête POST.
Vérifiez que la charge utile JSON existe dans le compartiment S3.
Grand succès!!!
J’espère que vous avez apprécié cette lecture. Vous pouvez appliquer ce modèle d’intégration pour une grande variété de cas d’utilisation pour ingérer des données et des documents via l’API pour un traitement événementiel. Si vous avez des questions, n’hésitez pas à les poster ici ou à me contacter sur LinkedIn.