Serverlös databehandling med AWS Lambda, del 2

Den första halvan av den här artikeln presenterade en översikt över serverlös datorer med AWS Lambda, inklusive att bygga, distribuera och testa AWS Lambda-funktioner i ett exempel på ett Java-program. I del 2 lär du dig hur du integrerar Lambda-funktioner med en extern databas, i detta fall DynamoDB. Vi använder sedan AWS SDK för att åberopa Lambda-funktioner från vårt exempel på Java-applikation.

AWS Lambda och DynamoDB

DynamoDB är en NoSQL-dokumentbutik som är värd för Amazon Web Services (AWS). DynamoDB definierar dataabstraktioner som tabeller som accepterar vanliga databasåtgärder som infoga, hämta, fråga, uppdatera och ta bort. Som med många andra NoSQL-databaser är DynamoDBs schema inte fixat, så vissa objekt i samma tabell kan ha fält som andra inte gör.

En av DynamoDB: s bästa funktioner är den differentierade prismodellen. Till skillnad från AWS Relational Database Service (RDS), där AWS hanterar din databas med hjälp av EC2-instanser som du betalar för, är DynamoDB pay-as-you-go. Du betalar för lagring du använder och genomströmningen av dina frågor, men du betalar inte direkt för några underliggande virtuella maskiner. Dessutom ger AWS dig en gratis nivå som stöder upp till 25 GB utrymme, med tillräcklig kapacitet för att utföra upp till 200 miljoner förfrågningar per månad.

I Serverless computing med AWS Lambda, del 1, utvecklade vi en enkel, serverlös Java-applikation med Lambda-funktioner. Du kan ladda ner källkoden för GetWidgetHandler-applikationen när som helst. Om du inte redan har läst del 1 föreslår jag att du känner till applikationskoden och exempel från den artikeln innan du fortsätter.

Vårt första steg är att konfigurera DynamoDB-databasen i vår AWS-konsol. Därefter uppdaterar vi get-widgetfunktionen från del 1 för att hämta en widget från en DynamoDB-tabell.

Ställ in DynamoDB-databasen i AWS

Vi börjar med att skapa DynamoDB-tabellen. Från AWS-konsolen klickar du på Tjänster och väljer DynamoDB från databassektionen, som visas i figur 1.

Steven Haines

När du väl startat ser du DynamoDB-instrumentpanelen. Klicka på knappen Skapa tabell för att börja skapa din tabell, som visas i figur 2.

Steven Haines

Nu ser du sidan som visas i figur 3.

Steven Haines

Ge ditt bord ett namn (i detta fall "Widget") och ställ in den primära nyckeln till id, lämna den som en String. Genom att trycka på Skapa när du är klar kommer du till sidan DynamoDB-tabeller. Om du behöver navigera till den här sidan i framtiden väljer du Tjänster -> DynamoDB och klickar på Tabeller .

Steven Haines

Vi skapar en post manuellt i den nya widgettabellen, så klicka på knappen Skapa objekt som visas i figur 5.

Steven Haines

DynamoDB fyller i förväg ut sidan Skapa artikel med idfältet. Ange ett ID som är lätt att komma ihåg, till exempel "1". Tryck sedan på plustecknet (+) bredvid det nya ID-numret och lägg till ett annat fält som heter name. Ange ett värde för namefältet, till exempel "Widget 1". Tryck på Spara när du är klar.

Uppdatera klassen GetWidgetHandler

Med data i vår databas är nästa sak vi behöver göra att uppdatera GetWidgetHandlerklassen från del 1. Vi börjar med att lägga till DynamoDB-beroendet i vår ursprungliga POM-fil. Den uppdaterade pom.xmlfilen visas i Listing 1.

Listning 1. pom.xml (uppdaterad med DynamoDB-beroende)

 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        

Listning 1 lägger till aws-java-sdk-dynamodbberoendet till POM-filen från del 1. Listning 2 visar den uppdaterade GetWidgetHandlerklassen.

Listing 2. GetWidgetHandler.java (uppdaterad för att ladda data från 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(); } } } 

Huvudgränssnittet till DynamoDB är DynamoDBobjektet. För att skapa en DynamoDBinstans behöver vi en DynamoDB-klient. Eftersom vår Lambda-funktion körs i AWS, behöver vi inte tillhandahålla referenser, så vi kan använda standardklienten. Observera att vi bara kan fråga databasen utan autentiseringsuppgifter eftersom get-widget-rolefrån del 1 har dynamodb:GetItembehörighet.

Från DynamoDBinstansen kan vi ringa för getTable("Widget")att hämta en Tableinstans. Då kan vi kalla getItem()Tablefall passerar den primära nyckeln för objektet som vi vill hämta. Om det finns ett objekt med den angivna primära nyckeln returnerar det ett giltigt svar. annars återkommer den null. I Itemklassen ger tillgång till svarsparametrar, så vi avsluta genomförandet genom att skapa ett nytt Widgetobjekt med namnet laddas från DynamoDB.

ladda ner Skaffa koden Hämta koden för den uppdaterade GetWidgetHandler-applikationen. Skapad av Steven Haines för JavaWorld.

Fråga DynamoDB med DynamoDBMapper

Det finns flera API: er för att fråga DynamoDB, från ett RESTful serviceanrop, till lågnivågränssnittet ovan, till ett par gränssnitt på högre nivå. Ett av de mer populära gränssnitten är DynamoDBMapper. Detta gränssnitt ger en liknande konstruktion som vad du kan hitta när du mappar objekt till relationsdata i ett verktyg som Hibernate. Låt oss kort granska hur man hämtar en Widgetfrån DynamoDB med DynamoDBMapperAPI: et.

Det första vi behöver göra är att lägga till några kommentarer till Widgetklassen, som visas i Listing 3.

Listing 3. Widget.java (uppdaterad med DynamoDBMapper-anteckningar)

 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; } } 

Den DynamoDBTableanteckning anger namnet på den DynamoDB tabellen till vilken Widgetkartor. Den DynamoDBHashKeyanteckning identifierar primärnyckeln i Widgettabellen. Och DynamoDBAttributeanteckningen identifierar andra klassattribut som mappar till databasattribut i DynamoDB. Om du hade andra attribut som du ville ignorera kan du lägga till @DynamoDBIgnoreanteckningen.

Med Widgetklassen kommenterad kan vi nu uppdatera GetWidgetHandlerklassen så att den används DynamoDBMapper, vilket visas i Listing 4.

Listning 4. GetWidgetHandler.java (uppdaterad med 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; } } 

I den tidigare (del 1) versionen av GetWidgetHandlerskapade vi en AmazonDynamoDBinstans med ett AmazonDynamoDBClientBuilder.defaultClient()samtal. Nu använder vi den klienten för att initialisera en DynamoDBMapperinstans istället.

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.

Om du råkar stöta på en OutOfMemoryErrornär du testar om din funktion, välj fliken Konfiguration och öppna avsnittet Avancerade inställningar. Här kan du öka ditt minne, som visas nedan.

Steven Haines