Blog ENI : Toute la veille numérique !
🐠 -25€ dès 75€ 
+ 7 jours d'accès à la Bibliothèque Numérique ENI. Cliquez ici
Accès illimité 24h/24 à tous nos livres & vidéos ! 
Découvrez la Bibliothèque Numérique ENI. Cliquez ici
  1. Livres et vidéos
  2. AWS Lambda
  3. Le développement d’API Serverless
Extrait - AWS Lambda Développez des micro-services en Java sur la plateforme serverless d'Amazon
Extraits du livre
AWS Lambda Développez des micro-services en Java sur la plateforme serverless d'Amazon
1 avis
Revenir à la page d'achat du livre

Le développement d’API Serverless

Introduction

Lors des chapitres précédents, vous avez acquis la maîtrise de l’écriture du code Java en environnement AWS Lambda. Vous avez appris comment implémenter des fonctions AWS Lambda en Java, avec ou sans les différents types d’interfaces RequestHandler, comment compiler et construire vos archives de déploiement, comment déployer, de manière rapide et efficace, vos applications et services sur l’infrastructure AWS Lambda, comment utiliser la console AWS ainsi que les outils de base comme IntelliJ IDEA, Maven, AWS CLI, SAM, CloundFormation, etc.

Notre travail commence à peine, car, à partir de ce chapitre, nous allons nous livrer à des cas d’utilisations plus typiques pour la pratique professionnelle quotidienne. Et quel cas d’utilisation plus typique qu’un microservice exposant une API de type RESTful ?

Pour mémoire, une API RESTful expose des services ayant un style d’architecture particulier, connu sous le nom de REpresentational State Transfer (https://fr.wikipedia.org/wiki/Representational_state_transfer).

Le scénario général

La figure ci-dessous présente le diagramme du scénario général qui sera implémenté au cours de l’ouvrage :

L’architecture logicielle de notre application

L’architecture logicielle de notre application

Le scénario général que nous vous proposons d’implémenter à partir de maintenant et jusqu’à la fin de cet ouvrage est celui d’une application fictive qui a pour but d’effectuer des transferts bancaires. Voici les étapes du flux des traitements :

1.

Tout commence lorsque des fichiers contenant des ordres de transferts bancaires, en format XML, arrivent dans un compartiment S3 dédié.

2.

L’arrivée de ces fichiers déclenche l’exécution d’une fonction AWS Lambda en Java qui est responsable du processus de unmarshalling des données XML en objets Java et de l’appel de l’API REST exposée grâce au service API Gateway d’AWS.

3.

Les points d’entrée de l’API REST exposés via le service API Gateway sont connectés à des fonctions Lambda en Java qui appliquent des transformations de formats et publient les messages qui en résultent dans une file d’attente SNS (Simple Notification Service).

4.

Une autre fonction Lambda en Java, qui est abonnée à recevoir des messages depuis cette file d’attente SNS, est déclenchée...

Le service API Gateway d’AWS

API Gateway est le service AWS qui permet de faire l’interface entre le back-end (y compris des fonctions Lambda) et le front-end comme le Web, le mobile ou les clients lourds. La figure ci-dessous en montre un exemple :

Le service API Gateway d’AWS

Le service API Gateway d’AWS

API Gateway offre des possibilités d’interfaçage avec les services suivants :

  • Proxy HTTP. Ce type d’intégration consiste à utiliser API Gateway comme un proxy pour rediriger des requêtes HTTP vers un serveur web comme, par exemple, Apache HTTP Server.

  • AWS Lambda. Il s’agit de notre cas d’utilisation où API Gateway est utilisé pour recevoir des requêtes HTTP et les convertir dans le bon format avant de les rediriger vers des fonctions Lambda.

  • Proxy service AWS. Ce type d’intégration est utilisé pour connecter une interface REST directement avec des services AWS comme, par exemple, DynamoDB, SNS, SQS, Kinesis, etc.

  • Mock. Ce type d’intégration est utilisé pour générer des réponses statiques, sans aucune implémentation derrière, pour faire des tests préliminaires d’une interface REST.

Le service API Gateway, à lui seul, pourrait être le sujet d’un ouvrage à part entière et, par conséquent, il ne s’agit pas de rentrer dans toutes les subtilités de son fonctionnement. La documentation complète se trouve, comme d’habitude, sur le site d’Amazon (https://docs.aws.amazon.com/apigateway/index.html). En revanche, nous allons nous concentrer sur son utilisation en tant que proxy pour des fonctions Lambda.

Mais avant de commencer, un bref rappel. Au chapitre AWS Lambda - Développement en Java, nous avons expliqué qu’il y avait deux types d’invocations de fonctions Lambda, synchrone et asynchrone, et nous avons présenté des exemples. API Gateway se conforme aux règles de l’invocation synchrone, à savoir que les points d’entrée sont appelés en mode requête/réponse, c’est-à-dire qu’une réponse est attendue à chaque requête. L’invocation asynchrone, se caractérise, elle, par le fait que les traitements ne sont pas suspendus en attente de réponse aux requêtes, mais...

Le projet Java

Commençons par la création du projet Java, sous IntelliJ IDEA, car c’est là que le plus important se passe.

 Assurez vous d’avoir installé un client GIT dans votre environnement de développement. Pour ce faire, suivez les instructions du guide d’installation pour votre système d’exploitation. Sous Ubuntu, qui est le système d’exploitation utilisé pour la rédaction de cet ouvrage, ce processus est très simple et se reduit à l’exécution de la commande suivante :

$ sudo apt update 
$ sudo apt install git 
... 
$ git -version 
git version 2.17.1 

 Clonez le projet Java qui accompagne le chapitre Le développement d’API Serverless :

$ git clone https://github.com/nicolasduminil/aws-lambda.git 
... 
$ cd chapter4 

 Ouvrez votre IDE si ce n’est pas déjà fait. Allez dans File - New - Project from existing sources et sélectionnez le sous-répertoire nommé chapter4 dans lequel vous aviez cloné le projet. Cliquez sur OK.

 Dans le nouvel écran intitulé Import Project qui s’affiche, cochez l’option Import project from external model et, dans la liste déroulante en dessous, sélectionnez Maven. Cliquez sur Finish.

Vous venez d’importer dans votre IDE le projet Java associé à ce chapitre. Il s’agit bien évidement d’un projet Maven, comme tous les autres, à la différence près que, cette fois-ci c’est un projet multi-module. En tant que développeur Java, nous connaissons bien les projets Maven et, notamment, les projets multi-modules. Mais juste pour mémoire, un projet Maven multi-module est un projet basé sur un pom.xml principal, qu’on appelle agrégé, et un certain nombre de pom.xml subordonnés, qu’on appelle modules maven.

1. Le module agrégé

Ouvrez maintenant le pom.xml du module agrégé :

<?xml version="1.0" encoding="UTF-8"?> 
<project xmlns="http://maven.apache.org/POM/4.0.0" 
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0...

Swagger ou OpenAPI

Exposons maintenant en tant qu’API les fonctions Lambda implémentées par les classes Java que nous venons d’examiner. Sur la plateforme AWS ceci se fait à l’aide du service API Gateway.

Nous pourrions donc aller dans la console AWS, sélectionner API Gateway et, en se servant de l’interface graphique proposée, naviguer parmi les dizaines d’options possibles et, au bout de probablement une heure de travail, arriver à un squelette fonctionnel. Et si les spécifications de notre API changent (c’est le cas très fréquemment dans la vie d’un projet), il faudra recommencer.

Nous n’allons pas procéder de la sorte. Notre ouvrage est, avant tout, focalisé sur le développement du code. Et qui dit code dit IaC. Nous allons donc appliquer une démarche de type IaC, consistant à définir notre API de manière déterministe et répétable, par l’intermédiaire d’un processus d’automatisation, grâce à des scripts. Ceci peut se faire de plusieurs manières, par exemple directement avec des commandes AWS CLI, ou avec des outils propriétaires comme CloudFormation, ou open-source comme TerraForm. Mais il y a aussi une autre alternative très utilisée par les développeurs et qui est basée sur Swagger, qui a été rebaptisé récemment OpenAPI.

Swagger est un ensemble d’outils logiciels open source pour concevoir, créer, documenter et utiliser les services RESTful, développé en 2011 par SmartBear Software. Il comprend une documentation automatisée, la génération de code et la génération de cas de test. En novembre 2015, la compagnie a annoncé son intention de créer, sous l’égide de la fondation Linux, une nouvelle organisation nommée OpenAPI Initiative. D’autres organisations majeures, comme IBM, Google et d’autres se sont associées à cette initiative en tant que membres fondateurs. En janvier 2016, Swagger a changé de nom pour devenir OpenAPI.

OpenAPI est un formalisme basé sur la notation YAML, et qui peut aussi s’exprimer en JSON, qui permet de définir une API REST de manière langage agnostique. Il existe à ce jour...

API Gateway

Nous avons créé notre projet maven multi-module contenant l’implémentation Java de nos fonctions Lambda. Nous venons de définir notre API en formalisme OpenAPI et de la connecter aux fonctions Lambda vis les extensions AWS d’OpenAPI. Il ne nous reste plus qu’à créer notre API dans API Gateway et l’y exposer. Là aussi, on pourrait procéder manuellement en utilisant la console AWS, mais le lecteur attentif sait désormais qu’il est préférable d’utiliser le fameux template SAM comme véhicule d’automatisation de l’ensemble. Examinons donc ce template :

AWSTemplateFormatVersion: '2010-09-09' 
Transform: 'AWS::Serverless-2016-10-31' 
Description: Chapter 4 samples 
Globals: 
  Function: 
    Runtime: java11 
    MemorySize: 512 
    Timeout: 10 
    Tracing: Active 
Parameters: 
  BucketName: 
    Type: String 
    Description: The name of the S3 bucket in which the OpenAPI 
specification is stored 
Resources: 
  SendMoneyRestAPI: 
    Type: AWS::Serverless::Api 
    Properties: 
      Name: 
        send-money-api 
      StageName: 
        dev 
      DefinitionBody: 
        Fn::Transform: 
          Name: AWS::Include 
          Parameters: 
            Location: 
              Fn::Join: 
                - '' 
                - - 's3://' 
                  - Ref:...

Déploiement et exécution

Nous arrivons au moment de la vérité, c’est-à-dire à la fin de notre exercice, là où on doit déployer et tester ce qu’on vient de faire. Est-ce que cela va fonctionner ? Examinons, pour commencer, le nouveau script deploy.sh :

#!/bin/bash 
RANDOM=$$ 
BUCKET_NAME=bucketname-$RANDOM 
STAGE_NAME=dev 
AWS_REGION=$(aws configure list | grep region | awk '{print $2}') 
aws s3 mb s3://$BUCKET_NAME 
echo $BUCKET_NAME > bucket-name.txt 
aws s3 cp openapi.yaml s3://$BUCKET_NAME/openapi.yaml 
sam deploy --s3-bucket $BUCKET_NAME --stack-name chapter4-stack --capabilities 
CAPABILITY_IAM --parameter-overrides BucketName=$BUCKET_NAME 
aws cloudformation wait stack-create-complete --stack-name chapter4-stack 
API_ID=$(aws apigateway get-rest-apis --query "items[?name=='send-money-api']. 
id" --output text) 
aws apigateway create-deployment --rest-api-id $API_ID --stage-name $ 
STAGE_NAME >/dev/null 2>&1 
echo "Your API with ID $API_ID is deployed and ready to be tested at 
https://$API_ID.execute-api.$AWS_REGION.amazonaws.com/$STAGE_NAME" 

On crée à nouveau, comme on le faisait précédemment, le compartiment S3 qui hébergera temporairement notre code Java, en faisant attention à lui accorder un nom unique, grâce à la concaténation du numéro aléatoire généré avec la fonction $$ de Linux. Mais cette fois-ci on copie dedans notre fichier openapi.yaml, car, vous vous en souvenez certainement, c’est à partir de là que notre template SAM, présenté plus haut, crée le corps de l’API. C’est ce que fait la commande aws s3 cp.

Ensuite on exécute, comme d’habitude, la commande sam deploy en lui passant comme paramètre le nom du compartiment S3. Il ne va pas échapper au lecteur attentif que le nom de ce compartiment est passé deux fois, une première fois via le paramètre -s3 et une deuxième fois via -parameter-overrides. Cela ne devrait pas être nécessaire, mais, une anomalie présente au moment de la rédaction de l’ouvrage, a fait que ce fût le seul contournement possible.

La commande aws cloudformation...