Ich habe eine Lambda-Funktion in Java geschrieben und mit SAM bereitgestellt

Einführung

Bisher habe ich AWS Lambda hauptsächlich in Python und manchmal in Node.js erstellt, aber zur Abwechslung habe ich untersucht, wie man in Java entwickelt, also werde ich es zusammenfassen.

Dieses Mal habe ich den Quellcode der in Java mit Gradle geschriebenen Lambda-Funktion erstellt und mit AWS SAM bereitgestellt. Das AWS Toolkit für Eclipse (https://docs.aws.amazon.com/ja_jp/toolkit-for-eclipse/v1/user-guide/welcome.html) wird auch für die Entwicklung in Eclipse bereitgestellt. Normalerweise entwickle ich mit Vim und stelle mit CLI bereit, also werde ich mich darauf einstellen.

Überprüfungsumgebung

Wichtige Punkte für die Entwicklung von Lambda mit Java

~~ Laufzeit ist nur Java 8 ~~ Laufzeit ist Java 8 und Java 11 (geändert am 19. November 2019)

~~ Wie Sie in der offiziellen Dokumentation unten sehen können, ist die einzige bereitgestellte Java-Laufzeit "Java 8" ("JDK 8"). Wenn Sie eine andere Version verwenden, müssen Sie warten, bis diese unterstützt wird, oder eine benutzerdefinierte Laufzeit verwenden. ~~

Java 11 wurde am 19. November 2019 hinzugefügt und die Laufzeit kann aus Java 8 (JDK 8) und Java 11 (JDK 11) ausgewählt werden.

Erstellen von Lambda-Funktionen mit Java-AWS Lambda

Bereitstellung als Zip- oder JAR-Datei

Packen und implementieren Sie eine in Java geschriebene Anwendung in einer Zip-Datei oder einem eigenständigen JAR.

Die offizielle Dokumentation zeigt, wie Sie mit Maven ein eigenständiges Glas und mit Gradle eine Zip-Datei bereitstellen. Dieses Mal habe ich die Methode zum Packen und Bereitstellen in einer Zip-Datei mit Gradle ausprobiert.

Java AWS Lambda-Bereitstellungspaket --AWS Lambda

Es gibt drei Möglichkeiten, Handlerfunktionsanforderungen zu empfangen und zurückzugeben

Es gibt mehrere Methoden, um die Anforderung der Handlerfunktion zu empfangen und die Antwort wie folgt zurückzugeben.

  1. Java einfacher Typ
  2. POJO-Typ (Plain Old Java Object)
  3. Stream-Typ

Die Art und Weise, wie die Handlerfunktion geschrieben wird, ist für jeden unterschiedlich. Mit anderen Worten, es gibt drei Möglichkeiten, Handlerfunktionen zu schreiben.

Es scheint, dass es unter dem Gesichtspunkt, welche Art von Daten gesendet werden, richtig verwendet wird, anstatt zu entscheiden, ob "Wenn Sie diesen Ereignisauslöser verwenden, dieser Typ". In dieser Situation scheint es so etwas nicht zu geben, daher muss überlegt werden, welche Methode bei der tatsächlichen Entwicklung von Lambda-Funktionen in Java verwendet werden soll.

Dieses Mal haben wir den "POJO-Typ" übernommen.

Handler-E / A-Typ (Java) --AWS Lambda

Was ich diesmal gemacht habe

Ich habe eine einfache Webanwendung erstellt, die "API Gateway" als Auslöser für Lambda-Funktionen verwendet. Es ist eine einfache API, die nur eine POST-Anfrage sendet und "Hallo" zurückgibt.

Beispielcode

Der Code, den ich erstellt habe, ist hier. https://github.com/mmclsntr/awslambda-javagradle

Projektstruktur

.
├── build/
│   ├── distributions/
│   │   └── awslambda-javagradle.zip   #Stellen Sie das vom Build generierte Paket bereit
│   └── ...
├── build.gradle                    #Gradle Build-Konfigurationsdatei
├── src/main/java/awslambda/javagradle
│   ├── Greeting.java            #Der Kern der App
│   ├── Handler.java             #Speichert Lambda-Handlerfunktionen
│   └── Response.java            #Formatieren Sie die Lambda-Antwort
└── template.yml                    #CloudFormation-Vorlagendatei
└── Andere Gradle-Dateien

Codierung

Handler-Klasse

Handler.java


package awslambda.javagradle;

import java.util.Collections;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;

public class Handler implements RequestHandler<Map<String, Object>, Response> {

	private static final Logger LOG = Logger.getLogger(Handler.class.getName());

	@Override
	public Response handleRequest(Map<String, Object> input, Context context) {
		LOG.info("received: " + input);
        LOG.setLevel(Level.INFO);

        Greeting greetingBody = new Greeting("Hello");

		return Response.builder()
				.setStatusCode(200)
				.setObjectBody(greetingBody)
				.build();
	}
}

Antwortklasse

Response.java


package awslambda.javagradle;

import java.nio.charset.StandardCharsets;
import java.util.Base64;
import java.util.Collections;
import java.util.Map;
import org.apache.log4j.Logger;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

public class Response {

	private final int statusCode;
	private final String body;
	private final Map<String, String> headers;
	private final boolean isBase64Encoded;

	public Response(int statusCode, String body, Map<String, String> headers, boolean isBase64Encoded) {
		this.statusCode = statusCode;
		this.body = body;
		this.headers = headers;
		this.isBase64Encoded = isBase64Encoded;
	}
	...

}

Grußklasse

Erstellen Sie eine supereinfache Anwendung, die Hello als Beispiel zurückgibt.

Greeting.java


package awslambda.javagradle;

public class Greeting {
    private String greetings;

    public Greeting(String greetings) {
        this.greetings = greetings;
    }
    public String getGreetings() {
        return greetings;
    }

    public void setGreetings(String greetings) {
        this.greetings = greetings;
    }
}

CloudFormation-Vorlage

template.yml


AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
    AWS Lambda Java with Gradle

Globals:
    Function:
        Timeout: 20

Resources:
  PostGreetingFunction:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: build/distributions/awslambda-javagradle.zip
      Handler: awslambda.javagradle.Handler::handleRequest
      Runtime: java8
      Events:
        GetOrder:
          Type: Api
          Properties:
            Path: /
            Method: post

Outputs:
    ApiEndpoint:
      Description: "API Gateway endpoint URL for Prod stage"
      Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/"

    PostGreetingFunction:
      Description: "PostGreeting Lambda Function ARN"
      Value: !GetAtt PostGreetingFunction.Arn

Bereitstellen

Erstellen Sie eine Build-Einstellungsdatei

build.gradle


apply plugin: 'java'

repositories {
    mavenCentral()
}

sourceCompatibility = 1.8
targetCompatibility = 1.8

dependencies {
    compile (
        'com.amazonaws:aws-lambda-java-core:1.1.0',
        'com.amazonaws:aws-lambda-java-log4j:1.0.0',
        'com.amazonaws:aws-lambda-java-events:1.1.0',
        'com.fasterxml.jackson.core:jackson-core:2.8.5',
        'com.fasterxml.jackson.core:jackson-databind:2.8.5',
        'com.fasterxml.jackson.core:jackson-annotations:2.8.5'
    )
}

// Task for building the zip file for upload
task buildZip(type: Zip) {
    from compileJava
    from processResources
    into('lib') {
        from configurations.runtime
    }
}

build.dependsOn buildZip

Bauen

Erstellen Sie mit dem Befehl Gradle.

gradle build

Bereitstellung mit AWS SAM

Erstellen Sie den S3-Bucket für das Bereitstellungsziel

aws s3 mb s3://<Stellen Sie den Ziel-S3-Bucket bereit> --aws-profile=<AWS-Profil>

Paket

Laden Sie mit sam package die ausführbare Datei in den oben erstellten S3-Bucket hoch und generieren Sie eine Vorlagendatei für die Bereitstellung.

sam package \
--s3-bucket <Stellen Sie den Namen des Ziel-S3-Buckets bereit> \
--s3-prefix <Name des Bereitstellungsziel-S3-Ordners(Präfix)※Irgendein> \
--output-template-file output.yml \
--profile <AWS-Profil>

Als Ausgabe wird eine Datei "output.yml" erstellt.

Bereitstellen

Verwenden Sie "sam deploy", um Lambda und API Gateway bereitzustellen.

sam deploy \
--template-file output.yml \
--stack-name awslambda-javagradle-greeting \
--capabilities CAPABILITY_IAM \
--profile <AWS-Profil>

Bestätigung

Nachdem die Lambda-Funktion und das API-Gateway in AWS erstellt wurden, senden wir eine POST-Anforderung an den Endpunkt.

Anfrage


curl -X POST https://xxxx.execute-api.ap-northeast-1.amazonaws.com/Prod/

Antwort


{"greetings":"Hello"}

Impressionen

Ich selbst benutze normalerweise kein Java, also habe ich eine Weile gebraucht, aber ich habe den Eindruck, dass es einfach zu machen war. Natürlich ist die Menge an Code größer als das Schreiben mit einer Skriptsprache wie Python, aber es ist attraktiv, eine rigorose Entwicklung ohne Server durchführen zu können.

Dieses Mal allein konnte ich die spezifischen Spezifikationen für das Schreiben in Java, wie z. B. mehrere Arten des Schreibens von Handlerfunktionen, nicht vollständig erfassen. Wenn ich es tatsächlich benutze, möchte ich es unter Berücksichtigung dieses Bereichs detailliert gestalten.

Gerüchten zufolge ist der erste Start langsam (ca. 5 Sekunden, bis er reagiert). Referenz: https://cero-t.hatenadiary.jp/entry/20160106/1452090214

Zusammenfassung

Ich konnte die Eigenschaften und den Codierungssinn der Lambda-Funktionsentwicklung mit Java erfassen. Wenn Sie von einem Servlet migrieren, ist meiner Meinung nach eine umfassende Renovierung erforderlich, aber es scheint, dass es als Ersatz verwendet werden kann.

Ich bin ein wenig besorgt über die Unterstützung dort, ob die Laufzeit Java 8 ist, wie es ist. .. Ich habe API Gateway als Auslöser verwendet, möchte aber auch andere Dienste ausprobieren.

Referenz

https://qiita.com/kamata1729/items/8d88ea10dd3bb61fa6cc https://qiita.com/riversun/items/7fcc06617b469aed8f27

Recommended Posts

Ich habe eine Lambda-Funktion in Java geschrieben und mit SAM bereitgestellt
Ich möchte eine Funktion mit Kotlin und Java erstellen!
Ich habe ein Routensuchprogramm in TDD geschrieben und versucht, es umzugestalten
Ich habe ein Programm zur Beurteilung von Primzahlen in Java geschrieben
Ich möchte für jedes Array mit Lambda-Ausdruck in Java
Ich habe ein Primfaktorisierungsprogramm in Java geschrieben
Schreiben Sie eine Klasse in Kotlin und nennen Sie sie in Java
Ich habe versucht, eine Anmeldefunktion mit Java zu erstellen
Ich habe versucht, mit Java und Spring eine Funktion / einen Bildschirm für den Administrator einer Einkaufsseite zu erstellen
Weisen Sie Variablen Java8-Lambda-Ausdrücke zu und verwenden Sie sie erneut
Ich möchte eine Liste mit Kotlin und Java erstellen!
Selbst in Java möchte ich true mit == 1 && a == 2 && a == 3 ausgeben
Ich habe ein PDF mit Java erstellt.
Ich habe Gordobachs Theorem in Java geschrieben
Ein Memo, als ich versuchte, "über das Schreiben einer Java-Anwendung in Eclipse und das Veröffentlichen in Kubernetes in einem Liberty-Container (Teil 1) zu sprechen".
Ich kann in IntelliJ keine Java-Klasse mit einem bestimmten Namen erstellen
Ich habe eine Sterling-Sorte geschrieben, die sich wie in Java anfühlt
Stellen Sie die Sensorinformationen von Raspberry Pi in Java grafisch dar und überprüfen Sie sie mit einem Webbrowser
Teilen Sie eine Zeichenfolge in Java mit ". (Dot)"
Behandeln Sie große JSON mit Java Lambda
Was mir bei der Verwendung der Schnittstelle einer Funktion mit Standardargumenten in Kotlin aus Java nicht gefällt
Ich habe ein Programm zur Beurteilung von Primzahlen in Java erstellt
Ich habe die Daten der Reise (Tagebuchanwendung) in Java erhalten und versucht, sie # 001 zu visualisieren
Lesen Sie eine Zeichenfolge in einer PDF-Datei mit Java
Erstellen Sie eine CSR mit erweiterten Informationen in Java
Sogar in Java möchte ich true mit == 1 && a == 2 && a == 3 ausgeben (Javassist zweite Abkochung)
Ich wollte (a == 1 && a == 2 && a == 3) in Java wahr machen
So komprimieren Sie eine JAVA-CSV-Datei und verwalten sie in einem Byte-Array
Bereiten Sie eine Scraping-Umgebung mit Docker und Java vor
Lassen Sie uns eine TODO-Anwendung mit Java 2 erstellen. Ich möchte eine Vorlage mit Spring Initializr erstellen und eine Hello-Welt erstellen
Verschlüsseln / Entschlüsseln mit AES256 in PHP und Java
Ich habe versucht, den Block mit Java zu brechen (1)
Selbst in Java möchte ich true mit == 1 && a == 2 && a == 3 (Black Magic) ausgeben.
[Java] Vorsichtsmaßnahmen beim Referenzieren in einer übergeordneten Klasse und beim Instanziieren in einer untergeordneten Klasse
Ich habe eine Funktion zum Registrieren von Bildern bei der API in Spring Framework erstellt. Teil 1 (API Edition)
Ich habe ein einfaches Berechnungsproblemspiel in Java gemacht
Versuchte Mastodons Toot- und Streaming-API in Java
[Ruby] Ich habe einen Crawler mit Anemone und Nokogiri gemacht.
Ich habe versucht, eine Clova-Fähigkeit in Java zu erstellen
Implementieren Sie Singleton mit Enum schnell in Java
Adressiert, da Azure-Funktionen in Java nicht mehr funktionieren
Ich möchte eine Funktion in der Rails Console definieren
Ich habe versucht, mit OCR eine PDF-Datei mit Java zu verarbeiten
Was ich beim Erstellen eines Servers in Java gelernt habe
Ausgabe true mit if (a == 1 && a == 2 && a == 3) in Java (Invisible Identifier)
So konvertieren Sie A in a und a in A mit logischem Produkt und Summe in Java
Ich habe jetzt einen Test mit Spring Boot + JUnit 5 geschrieben
[Java] Eine Technik zum Schreiben von Konstruktoren, Gettern und Setzern auf einmal mit IntelliJ IDEA.
Bis Sie mit Maven ein von Scala geschriebenes Projekt erstellen und es mit dem Befehl scala ausführen.
Ich habe eine Funktion zum Registrieren von Bildern bei der API in Spring Framework erstellt. Teil 2 (Client Edition)
Ich habe versucht, ein Programm in Java zu erstellen, das das Problem des Handlungsreisenden mit einem genetischen Algorithmus löst
In Java 2D-Karte speichern und mit for-Anweisung drehen
Ich habe einen CRUD-Test mit SpringBoot + MyBatis + DBUnit geschrieben (Teil 1)
Ich habe versucht, mit Chocolatey eine Java8-Entwicklungsumgebung zu erstellen
Implementieren Sie Thread in Java und versuchen Sie, die anonyme Klasse Lambda zu verwenden
Memorandum Nr. 4 "Holen Sie sich eine Zeichenkette und dekorieren Sie sie" [Java]
Ich habe versucht, eine Java EE-Anwendung mit OpenShift zu modernisieren.