Definieren des Lambda-Funktions-Handlers in Java - AWS Lambda

Definieren des Lambda-Funktions-Handlers in Java

Der Lambda-Funktionshandler ist die Methode in Ihrem Funktionscode, die Ereignisse verarbeitet. Wenn Ihre Funktion aufgerufen wird, führt Lambda die Handler-Methode aus. Ihre Funktion wird so lange ausgeführt, bis der Handler eine Antwort zurückgibt, beendet wird oder ein Timeout auftritt.

Auf dieser Seite wird beschrieben, wie Sie mit Lambda-Funktions-Handlern in Java arbeiten, einschließlich Optionen für die Projekteinrichtung, Benennungskonventionen und Best Practices. Diese Seite enthält auch ein Beispiel für eine Java-Lambda-Funktion, die Informationen über einen Auftrag aufnimmt, eine Textdatei als Quittung erstellt und diese Datei in einem Bucket von Amazon Simple Storage Service (Amazon S3) platziert. Informationen darüber, wie Sie Ihre Funktion nach dem Schreiben einsetzen können, finden Sie unter Bereitstellen von Java-Lambda-Funktionen mit ZIP- oder JAR-Dateiarchiven oder Bereitstellen von Java-Lambda-Funktionen mit Container-Images.

Einrichten Ihres Java-Handler-Projekts

Wenn Sie mit Lambda-Funktionen in Java arbeiten, umfasst der Prozess das Schreiben Ihres Codes, das Kompilieren und das Bereitstellen der kompilierten Artefakte in Lambda. Sie können ein Java-Lambda-Projekt auf verschiedene Arten initialisieren. Sie können beispielsweise Tools wie Maven Archetype für Lambda-Funktionen, den AWS SAM-CLI-Befehl sam init oder sogar eine Standard-Java-Projekteinrichtung in Ihrer bevorzugten IDE wie IntelliJ IDEA oder Visual Studio Code verwenden. Alternativ können Sie die erforderliche Dateistruktur manuell erstellen.

Ein typisches Java-Lambda-Funktionsprojekt folgt dieser allgemeinen Struktur:

/project-root └ src └ main └ java └ example └ OrderHandler.java (contains main handler) └ <other_supporting_classes> └ build.gradle OR pom.xml

Sie können entweder Maven oder Gradle verwenden, um Ihr Projekt zu erstellen und Abhängigkeiten zu verwalten.

Die Haupthandler-Logik für Ihre Funktion befindet sich in einer Java-Datei im Verzeichnis src/main/java/example. Im Beispiel auf dieser Seite nennen wir diese Datei OrderHandler.java. Neben dieser Datei können Sie bei Bedarf weitere Java-Klassen hinzufügen. Achten Sie beim Bereitstellen Ihrer Funktion in Lambda darauf, die Java-Klasse anzugeben, die die Haupthandler-Methode enthält, die Lambda bei einem Aufruf ausführen soll.

Beispiel für Java-Lambda-Funktionscode

Das folgende Beispiel für einen Java 21-Lambda-Funktionscode nimmt Informationen über eine Bestellung auf, erstellt eine Textdateiquittung und platziert diese Datei in einem Amazon-S3-Bucket.

Beispiel OrderHandler.java-Lambda-Funktion
package example; import com.amazonaws.services.lambda.runtime.Context; import com.amazonaws.services.lambda.runtime.RequestHandler; import software.amazon.awssdk.core.sync.RequestBody; import software.amazon.awssdk.services.s3.S3Client; import software.amazon.awssdk.services.s3.model.PutObjectRequest; import software.amazon.awssdk.services.s3.model.S3Exception; import java.nio.charset.StandardCharsets; /** * Lambda handler for processing orders and storing receipts in S3. */ public class OrderHandler implements RequestHandler<OrderHandler.Order, String> { private static final S3Client S3_CLIENT = S3Client.builder().build(); /** * Record to model the input event. */ public record Order(String orderId, double amount, String item) {} @Override public String handleRequest(Order event, Context context) { try { // Access environment variables String bucketName = System.getenv("RECEIPT_BUCKET"); if (bucketName == null || bucketName.isEmpty()) { throw new IllegalArgumentException("RECEIPT_BUCKET environment variable is not set"); } // Create the receipt content and key destination String receiptContent = String.format("OrderID: %s\nAmount: $%.2f\nItem: %s", event.orderId(), event.amount(), event.item()); String key = "receipts/" + event.orderId() + ".txt"; // Upload the receipt to S3 uploadReceiptToS3(bucketName, key, receiptContent); context.getLogger().log("Successfully processed order " + event.orderId() + " and stored receipt in S3 bucket " + bucketName); return "Success"; } catch (Exception e) { context.getLogger().log("Failed to process order: " + e.getMessage()); throw new RuntimeException(e); } } private void uploadReceiptToS3(String bucketName, String key, String receiptContent) { try { PutObjectRequest putObjectRequest = PutObjectRequest.builder() .bucket(bucketName) .key(key) .build(); // Convert the receipt content to bytes and upload to S3 S3_CLIENT.putObject(putObjectRequest, RequestBody.fromBytes(receiptContent.getBytes(StandardCharsets.UTF_8))); } catch (S3Exception e) { throw new RuntimeException("Failed to upload receipt to S3: " + e.awsErrorDetails().errorMessage(), e); } } }

Diese OrderHandler.java-Datei enthält die folgenden Abschnitte des Codes:

  • package example: In Java kann dies beliebig sein, muss jedoch mit der Verzeichnisstruktur Ihres Projekts übereinstimmen. Hier verwenden wir package example, da die Verzeichnisstruktur src/main/java/example lautet.

  • import-Anweisungen: Damit können Sie Java-Klassen importieren, die für Ihre Lambda-Funktion erforderlich sind.

  • public class OrderHandler ...: Dies definiert Ihre Java-Klasse und muss eine gültige Klassendefinition sein.

  • private static final S3Client S3_CLIENT ...: Dadurch wird ein S3-Client außerhalb einer der Methoden der Klasse initialisiert. Dies veranlasst Lambda, diesen Code während der Initialisierungsphase auszuführen.

  • public record Order ...: Definieren Sie die Form des erwarteten Eingabeereignisses in diesem benutzerdefinierten Java-Datensatz.

  • public String handleRequest(Order event, Context context): Dies ist die Haupthandler-Methode, die Ihre Hauptanwendungslogik enthält.

  • private void uploadReceiptToS3(...) {}: Dies ist eine Hilfsmethode, auf die von der handleRequest-Haupthandler-Methode verwiesen wird.

Die folgende build.gradle- oder pom.xml-Datei gehört zu dieser Funktion.

build.gradle
plugins { id 'java' } repositories { mavenCentral() } dependencies { implementation 'com.amazonaws:aws-lambda-java-core:1.2.3' implementation 'software.amazon.awssdk:s3:2.28.29' implementation 'org.slf4j:slf4j-nop:2.0.16' } task buildZip(type: Zip) { from compileJava from processResources into('lib') { from configurations.runtimeClasspath } } java { sourceCompatibility = JavaVersion.VERSION_21 targetCompatibility = JavaVersion.VERSION_21 } build.dependsOn buildZip
pom.xml
<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 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.example</groupId> <artifactId>example-java</artifactId> <packaging>jar</packaging> <version>1.0-SNAPSHOT</version> <name>example-java-function</name> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>21</maven.compiler.source> <maven.compiler.target>21</maven.compiler.target> </properties> <dependencies> <dependency> <groupId>com.amazonaws</groupId> <artifactId>aws-lambda-java-core</artifactId> <version>1.2.3</version> </dependency> <dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>s3</artifactId> <version>2.28.29</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-nop</artifactId> <version>2.0.16</version> </dependency> </dependencies> <build> <plugins> <plugin> <artifactId>maven-surefire-plugin</artifactId> <version>3.5.2</version> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-shade-plugin</artifactId> <version>3.4.1</version> <configuration> <createDependencyReducedPom>false</createDependencyReducedPom> <filters> <filter> <artifact>*:*</artifact> <excludes> <exclude>META-INF/*</exclude> <exclude>META-INF/versions/**</exclude> </excludes> </filter> </filters> </configuration> <executions> <execution> <phase>package</phase> <goals> <goal>shade</goal> </goals> </execution> </executions> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.13.0</version> <configuration> <release>21</release> </configuration> </plugin> </plugins> </build> </project>

Damit diese Funktion ordnungsgemäß funktioniert, muss ihre Ausführungsrolle die s3:PutObject-Aktion zulassen. Stellen Sie außerdem sicher, dass Sie die RECEIPT_BUCKET-Umgebungsvariable definieren. Nach einem erfolgreichen Aufruf sollte der Amazon-S3-Bucket eine Empfangsdatei enthalten.

Anmerkung

Diese Funktion erfordert möglicherweise zusätzliche Konfigurationseinstellungen, um ohne Zeitüberschreitung erfolgreich ausgeführt zu werden. Wir empfehlen, 256 MB Arbeitsspeicher und eine Zeitüberschreitung von 10 Sekunden zu konfigurieren. Der erste Aufruf kann aufgrund eines Kaltstarts zusätzliche Zeit in Anspruch nehmen. Nachfolgende Aufrufe sollten aufgrund der Wiederverwendung der Ausführungsumgebung wesentlich schneller ausgeführt werden.

Gültige Klassendefinitionen für Java-Handler

Zum Definieren Ihrer Klasse definiert die Bibliothek aws-lambda-java-core zwei Schnittstellen für Handler-Methoden. Verwenden Sie die bereitgestellten Schnittstellen, um die Handler-Konfiguration zu vereinfachen und die Methodensignatur zur Kompilierzeit zu validieren.

Die RequestHandler-Schnittstelle ist ein generischer Typ, der zwei Parameter verwendet: den Eingabetyp und den Ausgabetyp. Beide Typen müssen Objekte sein. In diesem Beispiel implementiert unsere OrderHandler-Klasse RequestHandler<OrderHandler.Order, String>. Der Eingabetyp ist der Order-Datensatz, den wir innerhalb der Klasse definieren, und der Ausgabetyp ist String.

public class OrderHandler implements RequestHandler<OrderHandler.Order, String> { ... }

Wenn Sie diese Schnittstelle verwenden, deserialisiert die Java-Laufzeit das Ereignis in das Objekt mit dem Eingabetyp und serialisiert die Ausgabe in Text. Verwenden Sie diese Schnittstelle, wenn die integrierte Serialisierung mit Ihren Ein- und Ausgabetypen funktioniert.

Um Ihre eigene Serialisierung zu verwenden, können Sie die RequestStreamHandler-Schnittstelle implementieren. Mit dieser Schnittstelle übergibt Lamda Ihrem Handler einen Eingabestream und einen Ausgabestream. Der Handler liest Bytes aus dem Eingabestream, schreibt in den Ausgabestream und gibt „void“ zurück. Ein Beispiel für die Verwendung der Java 21-Laufzeit finden Sie unter HandlerStream.java.

Wenn Sie in Ihrer Java-Funktion nur mit grundlegenden und generischen Typen (d. h. String, Integer, List oder Map) arbeiten, müssen Sie keine Schnittstelle implementieren. Wenn Ihre Funktion beispielsweise eine Map<String, String>-Eingabe akzeptiert und eine String zurückgibt, könnten Ihre Klassendefinition und Ihre Handler-Signatur wie folgt aussehen:

public class ExampleHandler { public String handleRequest(Map<String, String> input, Context context) { ... } }

Wenn Sie keine Schnittstelle implementieren, ist das Kontextobjekt außerdem optional. Ihre Klassendefinition und Ihre Handler-Signatur könnten beispielsweise wie folgt aussehen:

public class NoContextHandler { public String handleRequest(Map<String, String> input) { ... } }

Namenskonventionen für Handler

Wenn Sie für Lambda-Funktionen in Java entweder die RequestHandler- oder RequestStreamHandler-Schnittstelle implementieren, muss Ihre Haupthandler-Methode handleRequest heißen. Fügen Sie außerdem das Tag @Override über Ihrer handleRequest-Methode ein. Wenn Sie Ihre Funktion in Lambda bereitstellen, geben Sie den Haupthandler in der Konfiguration Ihrer Funktion im folgenden Format an:

  • <Paket>.<Klasse> – Beispiel: example.OrderHandler.

Für Lambda-Funktionen in Java, die nicht die RequestHandler- oder RequestStreamHandler-Schnittstelle implementieren, können Sie einen beliebigen Namen für den Handler verwenden. Wenn Sie Ihre Funktion in Lambda bereitstellen, geben Sie den Haupthandler in der Konfiguration Ihrer Funktion im folgenden Format an:

  • <Paket>.<Klasse>::<Name_der_Handlermethode> – Beispiel: example.Handler::mainHandler.

Definieren Sie das Eingabeereignisobjekt und greifen Sie darauf zu

JSON ist das gebräuchlichste und standardmäßigste Eingabeformat für Lambda-Funktionen. In diesem Beispiel erwartet die Funktion eine Eingabe ähnlich der folgenden:

{ "orderId": "12345", "amount": 199.99, "item": "Wireless Headphones" }

Wenn Sie mit Lambda-Funktionen in Java 17 oder neuer arbeiten, können Sie die Form des erwarteten Eingabeereignisses als Java-Datensatz definieren. In diesem Beispiel definieren wir einen Datensatz innerhalb der OrderHandler-Klasse, um ein Order-Objekt darzustellen:

public record Order(String orderId, double amount, String item) {}

Dieser Datensatz entspricht der erwarteten Eingabeform. Nachdem Sie Ihren Datensatz definiert haben, können Sie eine Handler-Signatur schreiben, die eine JSON-Eingabe entgegennimmt, die der Datensatzdefinition entspricht. Die Java-Laufzeit deserialisiert diese JSON-Eingabe automatisch in ein Java-Objekt. Sie können dann auf die Felder des Objekts zugreifen. Zum Beispiel holt event.orderId den Wert von orderId aus der ursprünglichen Eingabe.

Anmerkung

Java-Datensätze sind nur in Java 17-Laufzeiten und neueren Versionen enthalten. In allen Java-Laufzeiten können Sie eine Klasse verwenden, um Ereignisdaten darzustellen. In solchen Fällen können Sie eine Bibliothek wie jackson verwenden, um JSON-Eingaben zu deserialisieren.

Andere Typen von Eingabeereignissen

Es gibt viele mögliche Eingabeereignisse für Lambda-Funktionen in Java:

  • Integer, Long, Double, usw. – Das Ereignis ist eine Zahl ohne zusätzliche Formatierung, zum Beispiel: ., 3.5. Die Java-Laufzeit wandelt den Wert in ein Objekt des angegebenen Typs um.

  • String – Das Ereignis ist eine JSON-Zeichenfolge mit Anführungszeichen, z. B, “My string”. Die Laufzeit wandelt den Wert in ein String-Objekt ohne Anführungszeichen um.

  • List<Integer>, List<String>, List<Object>, usw. – Das Ereignis ist ein JSON-Array. Die Laufzeitumgebung deserialisiert sie in ein Objekt des angegebenen Typs oder der angegebenen Schnittstelle.

  • InputStream – Das Ereignis ist ein beliebiger JSON-Typ. Die Laufzeit übergibt einen Bytestream des Dokuments ohne Änderung an den Handler. Sie deserialisieren die Eingabe und schreiben Ausgabe in einen Ausgabestream.

  • Bibliothekstyp – Bei Ereignissen, die von anderen AWS-Services gesendet werden, müssen Sie die Typen in der Bibliothek aws-lambda-java-events verwenden. Wenn Ihre Lambda-Funktion beispielsweise von Amazon Simple Queue Service (SQS) aufgerufen wird, verwenden Sie das SQSEvent-Objekt als Eingabe.

Zugreifen auf und Verwenden des Lambda-Kontextobjekts

Das Lambda-Kontextobjekt enthält Informationen über Aufruf, Funktion und Ausführungsumgebung. In diesem Beispiel ist das Kontextobjekt vom Typ com.amazonaws.services.lambda.runtime.Context und das zweite Argument der Haupthandlerfunktion.

public String handleRequest(Order event, Context context) { ... }

Wenn Ihre Klasse entweder die RequestHandler oder die RequestStreamHandler-Schnittstelle implementiert, ist das Kontextobjekt ein erforderliches Argument. Andernfalls ist das Kontextobjekt optional. Weitere Informationen zu gültigen akzeptierten Handlersignaturen finden Sie unter Gültige Klassendefinitionen für Java-Handler.

Wenn Sie mit dem AWS-SDK andere Dienste aufrufen, wird das Kontextobjekt in einigen wichtigen Bereichen benötigt. Um beispielsweise Funktionsprotokolle für Amazon CloudWatch zu erstellen, können Sie die context.getLogger()-Methode verwenden, um ein LambdaLogger-Objekt für die Protokollierung abzurufen. In diesem Beispiel können wir den Logger verwenden, um eine Fehlermeldung zu protokollieren, falls bei der Verarbeitung aus irgendeinem Grund ein Fehler auftritt:

context.getLogger().log("Failed to process order: " + e.getMessage());

Außerhalb der Protokollierung können Sie das Kontextobjekt auch für die Funktionsüberwachung verwenden. Weitere Informationen über das Kontextobjekt finden Sie unter Verwenden des Lambda-Kontextobjekts zum Abrufen von Java-Funktionsinformationen.

Verwenden des AWS SDK für Java v2 in Ihrem Handler

Oft verwenden Sie Lambda-Funktionen, um mit anderen AWS-Ressourcen zu interagieren oder diese zu aktualisieren. Die einfachste Art, eine Schnittstelle zu diesen Ressourcen herzustellen, ist die Verwendung des AWS SDK für Java v2.

Anmerkung

Das AWS SDK für Java (v1) befindet sich im Wartungsmodus und der Support wird am 31. Dezember 2025 eingestellt. Wir empfehlen, künftig nur noch das AWS SDK für Java v2 zu verwenden.

Um SDK-Abhängigkeiten zu Ihrer Funktion hinzuzufügen, fügen Sie diese in Ihrer build.gradle-Datei für Gradle oder der pom.xml-Datei für Maven hinzu. Wir empfehlen, nur die Bibliotheken hinzuzufügen, die Sie für Ihre Funktion benötigen. Im Beispielcode zuvor haben wir die Bibliothek software.amazon.awssdk.services.s3 verwendet. In Gradle können Sie diese Abhängigkeit hinzufügen, indem Sie die folgende Zeile in den Abhängigkeitenabschnitt von build.gradle einfügen:

implementation 'software.amazon.awssdk:s3:2.28.29'

Fügen Sie in Maven die folgenden Zeilen im <dependencies>-Abschnitt von pom.xml hinzu:

<dependency> <groupId>software.amazon.awssdk</groupId> <artifactId>s3</artifactId> <version>2.28.29</version> </dependency>
Anmerkung

Dies ist möglicherweise nicht die neueste Version des SDK. Wählen Sie die geeignete SDK-Version für Ihre Anwendung.

Importieren Sie dann die Abhängigkeiten direkt in Ihree Java-Klasse:

import software.amazon.awssdk.services.s3.S3Client; import software.amazon.awssdk.services.s3.model.PutObjectRequest; import software.amazon.awssdk.services.s3.model.S3Exception;

Der Beispielcode initialisiert dann einen Amazon-S3-Client wie folgt:

private static final S3Client S3_CLIENT = S3Client.builder().build();

In diesem Beispiel haben wir unseren Amazon-S3-Client außerhalb der Haupt-Handler-Funktion initialisiert, um zu vermeiden, dass wir ihn bei jedem Aufruf unserer Funktion initialisieren müssen. Nachdem Sie Ihren SDK-Client initialisiert haben, können Sie ihn für die Interaktion mit anderen AWS-Services verwenden. Der Beispielcode ruft die Amazon S3 PutObject-API wie folgt auf:

PutObjectRequest putObjectRequest = PutObjectRequest.builder() .bucket(bucketName) .key(key) .build(); // Convert the receipt content to bytes and upload to S3 S3_CLIENT.putObject(putObjectRequest, RequestBody.fromBytes(receiptContent.getBytes(StandardCharsets.UTF_8)));

Zugriff auf Umgebungsvariablen

In Ihrem Handler-Code können Sie mithilfe der System.getenv()-Methode auf beliebige Umgebungsvariablen verweisen. In diesem Beispiel verweisen wir mit der folgenden Codezeile auf die definierte RECEIPT_BUCKET-Umgebungsvariable:

String bucketName = System.getenv("RECEIPT_BUCKET"); if (bucketName == null || bucketName.isEmpty()) { throw new IllegalArgumentException("RECEIPT_BUCKET environment variable is not set"); }

Verwenden des globalen Zustands

Lambda führt Ihren statischen Code und den Klassenkonstruktor während der Initialisierungsphase aus, bevor Ihre Funktion zum ersten Mal aufgerufen wird. Ressourcen, die während der Initialisierung erstellt werden, bleiben zwischen Aufrufen im Speicher, sodass Sie sie nicht bei jedem Aufruf Ihrer Funktion neu erstellen müssen.

Im Beispielcode befindet sich der Initialisierungscode des S3-Clients außerhalb der Haupt-Handler-Methode. Die Laufzeit initialisiert den Client, bevor die Funktion ihr erstes Ereignis ausführt, und der Client bleibt für die Wiederverwendung bei allen Aufrufen verfügbar.

Bewährte Codemethoden für Java-Lambda-Funktionen

Halten Sie sich an die Richtlinien in der folgenden Liste, um beim Erstellen Ihrer Lambda-Funktionen die besten Codierungspraktiken anzuwenden:

  • Trennen Sie den Lambda-Handler von Ihrer Core-Logik. Auf diese Weise können Sie eine Funktion zur besseren Prüfbarkeit von Einheiten schaffen.

  • Kontrollieren Sie die Abhängigkeiten im Bereitstellungspaket Ihrer Funktion. Die AWS Lambda-Ausführungsumgebung enthält eine Reihe von Bibliotheken. Um die neuesten Funktionen und Sicherheitsupdates zu aktivieren, wird Lambda diese Bibliotheken regelmäßig aktualisieren. Diese Updates können das Verhalten Ihrer Lambda-Funktion geringfügig verändern. Um die Abhängigkeiten, die Ihre Funktion verwendet, vollständig zu kontrollieren, empfehlen wir, alle Abhängigkeiten mit Ihrem Bereitstellungspaket zu bündeln.

  • Minimieren Sie die Komplexität Ihrer Abhängigkeiten. Ziehen Sie einfachere Frameworks vor, die sich schnell beim Start der Ausführungsumgebung laden lassen. Verwenden Sie beispielsweise einfachere Java Dependency Injection (IoC) Frameworks wie z. B. Dagger or Guice, als komplexere wie Spring Framework.

  • Minimieren Sie die Größe Ihres Bereitstellungspakets auf die für die Laufzeit erforderliche Größe. Dadurch verkürzt sich die Zeit, die für das Herunterladen und Entpacken Ihres Bereitstellungspakets vor dem Aufruf benötigt wird. Für Funktionen, die in Java erstellt wurden, sollten Sie das Hochladen der gesamten AWS SDK-Bibliothek als Teil Ihres Bereitstellungspakets vermeiden. Stattdessen sollten Sie selektiv von den Modulen ausgehen, die Komponenten des SDK aufnehmen, die Sie benötigen (z. B. DynamoDB, Amazon-S3-SDK-Module und Lambda-Kernbibliotheken).

Nutzen Sie die Wiederverwendung der Ausführungsumgebung zur Verbesserung Ihrer Funktion. Initialisieren Sie SDK-Clients und Datenbankverbindungen außerhalb des Funktions-Handlers und speichern Sie statische Komponenten lokal im /tmp-Verzeichnis. Nachfolgende Aufrufe, die von derselben Instance Ihrer Funktion verarbeitet werden, können diese Ressourcen wiederverwenden. Dies spart Kosten durch Reduzierung der Funktionslaufzeit.

Um potenzielle Datenlecks über Aufrufe hinweg zu vermeiden, verwenden Sie die Ausführungsumgebung nicht, um Benutzerdaten, Ereignisse oder andere Informationen mit Sicherheitsauswirkungen zu speichern. Wenn Ihre Funktion auf einem veränderbaren Zustand beruht, der nicht im Speicher innerhalb des Handlers gespeichert werden kann, sollten Sie für jeden Benutzer eine separate Funktion oder separate Versionen einer Funktion erstellen.

Verwenden Sie eine Keep-Alive-Direktive, um dauerhafte Verbindungen zu pflegen. Lambda bereinigt Leerlaufverbindungen im Laufe der Zeit. Der Versuch, eine Leerlaufverbindung beim Aufruf einer Funktion wiederzuverwenden, führt zu einem Verbindungsfehler. Um Ihre persistente Verbindung aufrechtzuerhalten, verwenden Sie die Keep-Alive-Direktive, die Ihrer Laufzeit zugeordnet ist. Ein Beispiel finden Sie unter Wiederverwenden von Verbindungen mit Keep-Alive in Node.js.

Verwenden Sie Umgebungsvariablen um Betriebsparameter an Ihre Funktion zu übergeben. Wenn Sie z. B. Daten in einen Amazon-S3-Bucket schreiben, anstatt den Bucket-Namen, in den Sie schreiben, hartzucodieren, konfigurieren Sie den Bucket-Namen als Umgebungsvariable.

Vermeiden Sie rekursive Aufrufe in Ihrer Lambda-Funktion, bei denen die Funktion sich selbst aufruft oder einen Prozess initiiert, der die Funktion erneut aufrufen kann. Dies kann zu unvorhergesehenen Mengen an Funktionsaufrufen führen und höhere Kosten zur Folge haben. Wenn Sie eine unbeabsichtigte Menge von Aufrufen feststellen, legen Sie die reservierte gleichzeitige Ausführung der Funktion auf 0 fest, um sofort alle Aufrufe der Funktion zu drosseln, während Sie den Code aktualisieren.

Verwenden Sie keine nicht dokumentierten, nicht öffentlichen APIs in Ihrem Lambda-Funktionscode. Für AWS Lambda-verwaltete Laufzeiten wendet Lambda regelmäßig Sicherheits- und Funktionsupdates auf Lambdas interne APIs an. Diese internen API-Updates können abwärtskompatibel sein, was zu unbeabsichtigten Konsequenzen wie Aufruffehlern führt, wenn Ihre Funktion von diesen nicht öffentlichen APIs abhängig ist. Eine Liste öffentlich zugänglicher APIs finden Sie in der API-Referenz.

Schreiben Sie idempotenten Code. Das Schreiben idempotenter Code für Ihre Funktionen stellt sicher, dass doppelte Ereignisse auf die gleiche Weise behandelt werden. Ihr Code sollte Ereignisse ordnungsgemäß validieren und doppelte Ereignisse ordnungsgemäß behandeln. Weitere Informationen finden Sie unter Wie mache ich meine Lambda-Funktion idempotent?.

  • Vermeiden der Verwendung von Java-DNS-Cache. Lambda-Funktionen speichern DNS-Antworten bereits im Cache. Wenn Sie einen anderen DNS-Cache verwenden, kann es zu Verbindungs-Timeouts kommen.

    Die java.util.logging.Logger-Klasse kann indirekt den JVM-DNS-Cache aktivieren. Um die Standardeinstellungen zu überschreiben, setzen Sie networkaddress.cache.ttl auf 0, bevor Sie logger initialisieren. Beispiel:

    public class MyHandler { // first set TTL property static{ java.security.Security.setProperty("networkaddress.cache.ttl" , "0"); } // then instantiate logger var logger = org.apache.logging.log4j.LogManager.getLogger(MyHandler.class); }
  • Reduzieren Sie den Zeitaufwand, den Lambda für das Entpacken von Bereitstellungspaketen benötigt, die in Java erstellt wurden, indem Sie Ihre Abhängigkeitsdateien .jar in einem separaten /lib-Verzeichnis ablegen. Dies geht schneller, als den gesamten Code Ihrer Funktion in einem einzigen Jar mit einer großen Anzahl von .class Dateien zu speichern. Detaillierte Anweisungen finden Sie unter Bereitstellen von Java-Lambda-Funktionen mit ZIP- oder JAR-Dateiarchiven.