Informatique sans serveur avec AWS Lambda, partie 2

La première moitié de cet article a présenté une vue d'ensemble de l'informatique sans serveur avec AWS Lambda, y compris la création, le déploiement et le test des fonctions AWS Lambda dans un exemple d'application Java. Dans la partie 2, vous apprendrez à intégrer des fonctions Lambda à une base de données externe, dans ce cas DynamoDB. Nous utiliserons ensuite le kit SDK AWS pour appeler des fonctions Lambda à partir de notre exemple d'application Java.

AWS Lambda et DynamoDB

DynamoDB est un magasin de documents NoSQL hébergé par Amazon Web Services (AWS). DynamoDB définit les abstractions de données comme des tables, qui acceptent les opérations de base de données courantes telles que l'insertion, la récupération, l'interrogation, la mise à jour et la suppression. Comme avec de nombreuses autres bases de données NoSQL, le schéma de DynamoDB n'est pas fixe, de sorte que certains éléments de la même table peuvent avoir des champs que d'autres n'ont pas.

L'une des meilleures fonctionnalités de DynamoDB est son modèle de tarification à plusieurs niveaux. Contrairement à AWS Relational Database Service (RDS), dans lequel AWS gère votre base de données à l'aide d'instances EC2 pour lesquelles vous payez, DynamoDB est pay-as-you-go. Vous payez pour le stockage que vous utilisez et le débit de vos requêtes, mais vous ne payez pas directement pour les machines virtuelles sous-jacentes. De plus, AWS vous offre un niveau gratuit prenant en charge jusqu'à 25 Go d'espace, avec un débit suffisant pour exécuter jusqu'à 200 millions de demandes par mois.

Dans l'informatique sans serveur avec AWS Lambda, partie 1, nous avons développé une application Java simple et sans serveur à l'aide des fonctions Lambda. Vous pouvez télécharger le code source de l'application GetWidgetHandler à tout moment. Si vous n'avez pas encore lu la partie 1, je vous suggère de vous familiariser avec le code de l'application et les exemples de cet article avant de continuer.

Notre première étape consiste à configurer la base de données DynamoDB dans notre console AWS. Après cela, nous mettrons à jour la get-widgetfonction de la partie 1 pour récupérer un widget d'une table DynamoDB.

Configurer la base de données DynamoDB dans AWS

Nous allons commencer par créer la table DynamoDB. Dans la console AWS, cliquez sur Services et choisissez DynamoDB dans la section de base de données, comme illustré dans la figure 1.

Steven Haines

Une fois lancé, vous verrez le tableau de bord DynamoDB. Cliquez sur le bouton Créer un tableau pour commencer à créer votre tableau, illustré à la figure 2.

Steven Haines

Vous verrez maintenant la page illustrée à la figure 3.

Steven Haines

Donnez un nom à votre table (dans ce cas "Widget") et définissez la clé primaire sur id, en la laissant comme un String. Appuyer sur Créer lorsque vous avez terminé vous dirigera vers la page des tableaux DynamoDB. Si vous devez accéder à cette page à l'avenir, sélectionnez Services -> DynamoDB et cliquez sur Tables .

Steven Haines

Nous créerons manuellement une entrée dans la nouvelle table Widget, cliquez donc sur le bouton Créer un élément illustré à la figure 5.

Steven Haines

DynamoDB pré-remplira la page Créer un élément avec le idchamp. Saisissez un identifiant facile à retenir, tel que «1». Ensuite, appuyez sur le plus (+) à côté du nouvel ID, en ajoutant un autre champ appelé name. Entrez une valeur pour le namechamp, telle que "Widget 1". Appuyez sur Enregistrer lorsque vous avez terminé.

Mettre à jour la classe GetWidgetHandler

Avec les données dans notre base de données, la prochaine chose que nous devons faire est de mettre à jour la GetWidgetHandlerclasse de la partie 1. Nous commencerons par ajouter la dépendance DynamoDB à notre fichier POM d'origine. Le pom.xmlfichier mis à jour est affiché dans la liste 1.

Listing 1. pom.xml (mis à jour avec la dépendance DynamoDB)

 4.0.0 com.javaworld.geekcap aws-lambda-java jar 1.0-SNAPSHOT aws-lambda-java //maven.apache.org  1.8 UTF-8    com.amazonaws aws-lambda-java-core 1.1.0   com.amazonaws aws-java-sdk-dynamodb 1.11.135   junit junit 4.12 test      org.apache.maven.plugins maven-compiler-plugin 2.0.2  ${java.version} ${java.version}    org.apache.maven.plugins maven-shade-plugin 2.3  false    package  shade        

Le listing 1 ajoute la aws-java-sdk-dynamodbdépendance au fichier POM de la partie 1. Le listing 2 montre la GetWidgetHandlerclasse mise à jour .

Listing 2. GetWidgetHandler.java (mis à jour pour charger les données de DynamoDB)

 package com.javaworld.awslambda.widget.handlers; import com.amazonaws.services.dynamodbv2.AmazonDynamoDB; import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder; import com.amazonaws.services.dynamodbv2.document.DynamoDB; import com.amazonaws.services.dynamodbv2.document.Item; import com.amazonaws.services.dynamodbv2.document.Table; import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.RequestHandler; import com.javaworld.awslambda.widget.model.Widget; import com.javaworld.awslambda.widget.model.WidgetRequest; public class GetWidgetHandler implements RequestHandler { @Override public Widget handleRequest(WidgetRequest widgetRequest, Context context) { //return new Widget(widgetRequest.getId(), "My Widget " + widgetRequest.getId()); // Create a connection to DynamoDB AmazonDynamoDB client = AmazonDynamoDBClientBuilder.defaultClient(); DynamoDB dynamoDB = new DynamoDB(client); // Get a reference to the Widget table Table table = dynamoDB.getTable("Widget"); // Get our item by ID Item item = table.getItem("id", widgetRequest.getId()); if(item != null) { System.out.println(item.toJSONPretty()); // Return a new Widget object return new Widget(widgetRequest.getId(), item.getString("name")); } else { return new Widget(); } } } 

La principale interface de DynamoDB est l' DynamoDBobjet. Pour créer une DynamoDBinstance, nous avons besoin d'un client DynamoDB. Étant donné que notre fonction Lambda s'exécutera dans AWS, nous n'avons pas besoin de fournir d'informations d'identification, nous pouvons donc utiliser le client par défaut. Notez que nous ne pourrons interroger la base de données sans informations d'identification que parce que la get-widget-rolepartie 1 a l' dynamodb:GetItemautorisation.

Depuis l' DynamoDBinstance, nous pouvons appeler getTable("Widget")pour récupérer une Tableinstance. Ensuite, nous pouvons appeler getItem()l' Tableinstance en lui passant la clé primaire de l'élément que nous voulons récupérer. S'il existe un élément avec la clé primaire spécifiée, il renverra une réponse valide; sinon il reviendra null. La Itemclasse donne accès aux paramètres de réponse, nous finissons donc l'implémentation en créant un nouvel Widgetobjet avec son nom chargé depuis DynamoDB.

download Obtenez le code Obtenez le code de l'application GetWidgetHandler mise à jour. Créé par Steven Haines pour JavaWorld.

Interroger DynamoDB avec DynamoDBMapper

Il existe plusieurs API pour interroger DynamoDB, d'un appel de service RESTful, à l'interface de bas niveau ci-dessus, à quelques interfaces de niveau supérieur. L'une des interfaces les plus populaires est DynamoDBMapper. Cette interface fournit une construction similaire à ce que vous pourriez trouver lors du mappage d'objets à des données relationnelles dans un outil comme Hibernate. Revoyons brièvement comment récupérer un à Widgetpartir de DynamoDB à l'aide de l' DynamoDBMapperAPI.

La première chose que nous devons faire est d'ajouter quelques annotations à la Widgetclasse, ce qui est montré dans le Listing 3.

Listing 3. Widget.java (mis à jour avec les annotations DynamoDBMapper)

 package com.javaworld.awslambda.widget.model; import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBAttribute; import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBHashKey; import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBTable; @DynamoDBTable(tableName="Widget") public class Widget { private String id; private String name; public Widget() { } public Widget(String id) { this.id = id; } public Widget(String id, String name) { this.id = id; this.name = name; } @DynamoDBHashKey(attributeName="id") public String getId() { return id; } public void setId(String id) { this.id = id; } @DynamoDBAttribute(attributeName="name") public String getName() { return name; } public void setName(String name) { this.name = name; } } 

L' DynamoDBTableannotation spécifie le nom de la table DynamoDB à laquelle les Widgetcorrespondances. L' DynamoDBHashKeyannotation identifie la clé primaire de la Widgettable. Et l' DynamoDBAttributeannotation identifie d'autres attributs de classe qui correspondent aux attributs de base de données dans DynamoDB. Si vous aviez d'autres attributs que vous vouliez ignorer, vous pouvez ajouter l' @DynamoDBIgnoreannotation.

Avec la Widgetclasse annotée, nous pouvons maintenant mettre à jour la GetWidgetHandlerclasse pour utiliser le DynamoDBMapper, qui est montré dans le Listing 4.

Listing 4. GetWidgetHandler.java (mis à jour avec DynamoDBMapper)

 package com.javaworld.awslambda.widget.handlers; import com.amazonaws.services.dynamodbv2.AmazonDynamoDB; import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClientBuilder; import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapper; import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.RequestHandler; import com.javaworld.awslambda.widget.model.Widget; import com.javaworld.awslambda.widget.model.WidgetRequest; public class GetWidgetHandler implements RequestHandler { @Override public Widget handleRequest(WidgetRequest widgetRequest, Context context) { // Create a connection to DynamoDB AmazonDynamoDB client = AmazonDynamoDBClientBuilder.defaultClient(); // Build a mapper DynamoDBMapper mapper = new DynamoDBMapper(client); // Load the widget by ID Widget widget = mapper.load(Widget.class, widgetRequest.getId()); if(widget == null) { // We did not find a widget with this ID, so return an empty Widget context.getLogger().log("No Widget found with ID: " + widgetRequest.getId() + "\n"); return new Widget(); } // Return the widget return widget; } } 

Dans l'ancienne version (partie 1) du, GetWidgetHandlernous avons créé une AmazonDynamoDBinstance à l'aide d'un AmazonDynamoDBClientBuilder.defaultClient()appel. Nous allons maintenant utiliser ce client pour initialiser une DynamoDBMapperinstance à la place.

The DynamoDBMapper class provides access to execute queries, load objects by ID, save objects, delete objects, and so forth. In this case, we pass DynamoDBMapper the widget's class (Widget.class) and its primary key. If DynamoDB has a Widget with the specified primary key it will return it; if not it will return null.

Rebuild and then re-upload your new JAR file by opening your Lambda function dashboard, then click on the Code tab and press Upload. When you re-upload and subsequently call your function, AWS Lambda will create a new container for the new JAR file and push that to an EC2 instance. You should expect the first run to be slow.

Si vous rencontrez un problème OutOfMemoryErrorlorsque vous testez à nouveau votre fonction, sélectionnez l' onglet Configuration et ouvrez la section Paramètres avancés. Ici, vous pouvez augmenter votre mémoire, comme indiqué ci-dessous.

Steven Haines