Die vorliegende Übersetzung wurde maschinell erstellt. Im Falle eines Konflikts oder eines Widerspruchs zwischen dieser übersetzten Fassung und der englischen Fassung (einschließlich infolge von Verzögerungen bei der Übersetzung) ist die englische Fassung maßgeblich.
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-Funktionshandlern in C# arbeiten, um mit der.NET-verwalteten Runtime zu arbeiten, einschließlich Optionen für die Projekteinrichtung, Benennungskonventionen und Best Practices. Diese Seite enthält auch ein Beispiel für eine C#-Lambda-Funktion, die Informationen über eine Bestellung aufnimmt, eine Textdateiquittung erstellt und diese Datei in einem Amazon Simple Storage Service (S3) -Bucket ablegt. Informationen darüber, wie Sie Ihre Funktion nach dem Schreiben einsetzen können, finden Sie unter Erstellen und Bereitstellen von C#-Lambda-Funktionen mit ZIP-Dateiarchiven oder Bereitstellen von .NET-Lambda-Funktionen mit Container-Images.
Richten Sie Ihr C#-Handler-Projekt ein
Wenn Sie mit Lambda-Funktionen in C# arbeiten, umfasst der Prozess das Schreiben Ihres Codes und das anschließende Bereitstellen Ihres Codes in Lambda. Es gibt zwei verschiedene Ausführungsmodelle für die Bereitstellung von Lambda-Funktionen in.NET: den Klassenbibliotheksansatz und den Ansatz für ausführbare Assemblys.
Beim Klassenbibliotheksansatz packen Sie Ihren Funktionscode als .NET-Assembly (.dll
) und stellen ihn mit der.NET Managed Runtime (dotnet8
) auf Lambda bereit. Für den Namen des Handlers erwartet Lambda eine Zeichenfolge im FormatAssemblyName::Namespace.Classname::Methodname
. Während der Initialisierungsphase der Funktion wird die Klasse Ihrer Funktion initialisiert und der gesamte Code im Konstruktor wird ausgeführt.
Beim Ansatz für ausführbare Assemblys verwenden Sie die Funktion für Anweisungen der obersten Ebenedotnet8
. Für den Namen des Handlers geben Sie Lambda den Namen der ausführbaren Assembly an, die ausgeführt werden soll.
Das Hauptbeispiel auf dieser Seite veranschaulicht den Ansatz einer Klassenbibliothek. Sie können Ihr C#-Lambda-Projekt auf verschiedene Arten initialisieren. Am einfachsten ist es jedoch, die .NET-CLI mit der CLI zu verwenden. Amazon.Lambda.Tools
Richten Sie die Amazon.Lambda.Tools
CLI ein, indem Sie die Schritte unter befolgenEinrichten der .NET-Entwicklungsumgebung. Initialisieren Sie dann Ihr Projekt mit dem folgenden Befehl:
dotnet new lambda.EmptyFunction --name ExampleCS
Dieser Befehl generiert die folgende Dateistruktur:
/project-root └ src └ ExampleCS └ Function.cs (contains main handler) └ Readme.md └ aws-lambda-tools-defaults.json └ ExampleCS.csproj └ test └ ExampleCS.Tests └ FunctionTest.cs (contains main handler) └ ExampleCS.Tests.csproj
In dieser Dateistruktur befindet sich die Haupthandlerlogik für Ihre Funktion in der Function.cs
Datei.
Beispiel für einen C#-Lambda-Funktionscode
Das folgende Beispiel für einen C#-Lambda-Funktionscode nimmt Informationen über eine Bestellung auf, erstellt eine Textdateiquittung und platziert diese Datei in einem Amazon S3 S3-Bucket.
Beispiel Function.cs
-Lambda-Funktion
using System;
using System.Text;
using System.Threading.Tasks;
using Amazon.Lambda.Core;
using Amazon.S3;
using Amazon.S3.Model;
// Assembly attribute to enable Lambda function logging
[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))]
namespace ExampleLambda;
public class Order
{
public string OrderId { get; set; } = string.Empty;
public double Amount { get; set; }
public string Item { get; set; } = string.Empty;
}
public class OrderHandler
{
private static readonly AmazonS3Client s3Client = new();
public async Task<string> HandleRequest(Order order, ILambdaContext context)
{
try
{
string? bucketName = Environment.GetEnvironmentVariable("RECEIPT_BUCKET");
if (string.IsNullOrWhiteSpace(bucketName))
{
throw new ArgumentException("RECEIPT_BUCKET environment variable is not set");
}
string receiptContent = $"OrderID: {order.OrderId}\nAmount: ${order.Amount:F2}\nItem: {order.Item}";
string key = $"receipts/{order.OrderId}.txt";
await UploadReceiptToS3(bucketName, key, receiptContent);
context.Logger.LogInformation($"Successfully processed order {order.OrderId} and stored receipt in S3 bucket {bucketName}");
return "Success";
}
catch (Exception ex)
{
context.Logger.LogError($"Failed to process order: {ex.Message}");
throw;
}
}
private async Task UploadReceiptToS3(string bucketName, string key, string receiptContent)
{
try
{
var putRequest = new PutObjectRequest
{
BucketName = bucketName,
Key = key,
ContentBody = receiptContent,
ContentType = "text/plain"
};
await s3Client.PutObjectAsync(putRequest);
}
catch (AmazonS3Exception ex)
{
throw new Exception($"Failed to upload receipt to S3: {ex.Message}", ex);
}
}
}
Diese Function.cs
-Datei enthält die folgenden Abschnitte des Codes:
-
using
Anweisungen: Verwenden Sie diese, um C#-Klassen zu importieren, die Ihre Lambda-Funktion benötigt. -
[assembly: LambdaSerializer(...)]
:LambdaSerializer
ist ein Assembly-Attribut, das Lambda anweist, JSON-Ereignisnutzlasten automatisch in C#-Objekte zu konvertieren, bevor sie an Ihre Funktion übergeben werden. -
namespace ExampleLambda
: Dies definiert den Namespace. In C# muss der Namespace-Name nicht mit dem Dateinamen übereinstimmen. -
public class Order {...}
: Dies definiert die Form des erwarteten Eingabeereignisses. -
public class OrderHandler {...}
: Dies definiert Ihre C#-Klasse. Darin definieren Sie die Haupthandler-Methode und alle anderen Hilfsmethoden. -
private static readonly AmazonS3Client s3Client = new();
: Dadurch wird ein Amazon S3 S3-Client mit der Standard-Credential-Provider-Kette außerhalb der Haupthandler-Methode initialisiert. Dies veranlasst Lambda, diesen Code während der Initialisierungsphase auszuführen. -
public async ... HandleRequest (Order order, ILambdaContext context)
: Dies ist die Haupthandler-Methode, die Ihre Hauptanwendungslogik enthält. -
private async Task UploadReceiptToS3(...) {}
: Dies ist eine Hilfsmethode, auf die von derhandleRequest
-Haupthandler-Methode verwiesen wird.
Da für diese Funktion ein Amazon S3 S3-SDK-Client erforderlich ist, müssen Sie ihn zu den Abhängigkeiten Ihres Projekts hinzufügen. Sie können dies tun, indem Sie zu dem folgenden Befehl navigieren src/ExampleCS
und ihn ausführen:
dotnet add package AWSSDK.S3
Standardmäßig enthält profile
die generierte aws-lambda-tools-defaults.json
Datei keine region
Informationen für Ihre Funktion. Aktualisieren Sie die function-handler
Zeichenfolge außerdem auf den richtigen Wert (ExampleCS::ExampleLambda.OrderHandler::HandleRequest
). Sie können diese Aktualisierung manuell vornehmen und die erforderlichen Metadaten hinzufügen, um ein bestimmtes Anmeldeinformationsprofil und eine bestimmte Region für Ihre Funktion zu verwenden. Ihre aws-lambda-tools-defaults.json
Datei sollte zum Beispiel in etwa so aussehen:
{
"Information": [
"This file provides default values for the deployment wizard inside Visual Studio and the AWS Lambda commands added to the .NET Core CLI.",
"To learn more about the Lambda commands with the .NET Core CLI execute the following command at the command line in the project root directory.",
"dotnet lambda help",
"All the command line options for the Lambda command can be specified in this file."
],
"profile": "default",
"region": "us-east-1",
"configuration": "Release",
"function-architecture": "x86_64",
"function-runtime": "dotnet8",
"function-memory-size": 512,
"function-timeout": 30,
"function-handler": "ExampleCS::ExampleLambda.OrderHandler::HandleRequest"
}
Damit diese Funktion ordnungsgemäß funktioniert, muss ihre Ausführungsrolle die s3:PutObject
-Aktion zulassen. Wenn Sie den dotnet lambda deploy-function
Befehl (d. h.dotnet lambda deploy-function ExampleCS
) verwenden, enthält die AWSLambdaExecute
Richtlinie in den CLI-Eingabeaufforderungen die erforderlichen Berechtigungen, damit Sie diese Funktion erfolgreich aufrufen können.
Stellen Sie außerdem sicher, dass
Stellen Sie abschließend sicher, dass Sie die RECEIPT_BUCKET
Umgebungsvariable definieren. Nach einem erfolgreichen Aufruf sollte der Amazon-S3-Bucket eine Empfangsdatei enthalten.
Handler für Klassenbibliotheken
Der Hauptbeispielcode auf dieser Seite veranschaulicht einen Klassenbibliothekshandler. Klassenbibliothekshandler haben die folgende Struktur:
[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))]
namespace NAMESPACE;
...
public class CLASSNAME {
public async Task<string> METHODNAME (...) {
...
}
}
Wenn Sie eine Lambda-Funktion erstellen, müssen Sie Lambda Informationen über den Handler Ihrer Funktion in Form einer Zeichenfolge im Feld Handler zur Verfügung stellen. Dadurch wird Lambda mitgeteilt, welche Methode in Ihrem Code ausgeführt werden soll, wenn Ihre Funktion aufgerufen wird. In C# lautet das Format der Handlerzeichenfolge für Klassenbibliothekshandler wie folgt: ASSEMBLY::TYPE::METHOD
-
ASSEMBLY
ist der Name der .NET-Assembly-Datei für Ihre Anwendung. Wenn Sie dieAmazon.Lambda.Tools
CLI zum Erstellen Ihrer Anwendung verwenden und den Assemblynamen nicht mithilfe derAssemblyName
Eigenschaft in der.csproj
Datei festlegen,ASSEMBLY
ist dies einfach der Name Ihrer.csproj
Datei. -
TYPE
ist der vollständige Name des Handlertyps, alsoNAMESPACE.CLASSNAME
. -
METHOD
ist der Name der Haupthandler-Methode in Ihrem Code, nämlichMETHODNAME
.
Wenn im Hauptbeispielcode auf dieser Seite die Assembly benannt istExampleCS
, dann lautet die vollständige HandlerzeichenfolgeExampleCS::ExampleLambda.OrderHandler::HandleRequest
.
Ausführbare Assembly-Handler
Sie können Lambda-Funktionen in C# auch als ausführbare Assembly definieren. Handler für ausführbare Assemblys nutzen die Funktion für Anweisungen der obersten Ebene von C#, bei der der Compiler die Main()
Methode generiert und Ihren Funktionscode darin ablegt. Bei der Verwendung ausführbarer Assemblys muss die Lambda-Laufzeit gebootet werden. Verwenden Sie dazu die LambdaBootstrapBuilder.Create
Methode in Ihrem Code. Die Eingaben für diese Methode sind die Haupthandlerfunktion sowie der zu verwendende Lambda-Serializer. Im Folgenden wird ein Beispiel für einen ausführbaren Assembly-Handler in C# gezeigt:
namespace GetProductHandler;
IDatabaseRepository repo = new DatabaseRepository();
await LambdaBootstrapBuilder.Create<APIGatewayProxyRequest>(Handler, new DefaultLambdaJsonSerializer())
.Build()
.RunAsync();
async Task<APIGatewayProxyResponse> Handler(APIGatewayProxyRequest apigProxyEvent, ILambdaContext context)
{
var id = apigProxyEvent.PathParameters["id"];
var databaseRecord = await this.repo.GetById(id);
return new APIGatewayProxyResponse
{
StatusCode = (int)HttpStatusCode.OK,
Body = JsonSerializer.Serialize(databaseRecord)
};
};
Im Feld Handler für ausführbare Assembly-Handler ist die Handlerzeichenfolge, die Lambda mitteilt, wie Ihr Code ausgeführt werden soll, der Name der Assembly. In diesem Beispiel ist das. GetProductHandler
Gültige Handler-Signaturen für C#-Funktionen
In C# nehmen gültige Lambda-Handler-Signaturen zwischen 0 und 2 Argumente an. In der Regel hat Ihre Handler-Signatur zwei Argumente, wie im Hauptbeispiel gezeigt:
public async Task<string> HandleRequest(Order order, ILambdaContext context)
Wenn Sie zwei Argumente angeben, muss das erste Argument die Ereigniseingabe und das zweite Argument das Lambda-Kontextobjekt sein. Beide Argumente sind optional. Die folgenden Signaturen sind beispielsweise auch gültige Lambda-Handler-Signaturen in C#:
-
public async Task<string> HandleRequest()
-
public async Task<string> HandleRequest(Order order)
-
public async Task<string> HandleRequest(ILambdaContext context)
Neben der Basissyntax der Handler-Signatur gibt es einige zusätzliche Einschränkungen:
-
Sie können das
unsafe
Schlüsselwort nicht in der Handler-Signatur verwenden. Sie können jedoch denunsafe
Kontext innerhalb der Handler-Methode und ihrer Abhängigkeiten verwenden. Weitere Informationen finden Sie unter unsafe (C#-Referenz)auf der Microsoft-Dokumentationswebsite. -
Der Handler darf das
params
Schlüsselwort nicht verwenden oder esArgIterator
als Eingabe- oder Rückgabeparameter verwenden. Diese Schlüsselwörter unterstützen eine variable Anzahl von Parametern. Die maximale Anzahl von Argumenten, die Ihr Handler akzeptieren kann, ist zwei. -
Der Handler ist möglicherweise keine generische Methode. Mit anderen Worten, es kann keine generischen Typparameter wie verwenden
<T>
. -
Lambda unterstützt keine asynchronen Handler mit
async void
in der Signatur.
Namenskonventionen für Handler
Lambda-Handler in C# haben keine strengen Namensbeschränkungen. Sie müssen jedoch sicherstellen, dass Sie Lambda die richtige Handlerzeichenfolge zur Verfügung stellen, wenn Sie Ihre Funktion bereitstellen. Die richtige Handlerzeichenfolge hängt davon ab, ob Sie einen Klassenbibliothekshandler oder einen ausführbaren Assembly-Handler bereitstellen.
Obwohl Sie einen beliebigen Namen für Ihren Handler verwenden können, sind Funktionsnamen in C# in der Regel in PascalCase. Auch wenn der Dateiname nicht mit dem Klassen- oder Handlernamen übereinstimmen muss, empfiehlt es sich im Allgemeinen, einen Dateinamen zu verwenden, als OrderHandler.cs
ob Ihr Klassenname lautetOrderHandler
. Sie können den Dateinamen in diesem Beispiel beispielsweise von Function.cs
bis ändernOrderHandler.cs
.
Serialisierung in C#-Lambda-Funktionen
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"
}
In C# können Sie die Form des erwarteten Eingabeereignisses in einer Klasse definieren. In diesem Beispiel definieren wir die Order
Klasse, um diese Eingabe zu modellieren:
public class Order
{
public string OrderId { get; set; } = string.Empty;
public double Amount { get; set; }
public string Item { get; set; } = string.Empty;
}
Wenn Ihre Lambda-Funktion andere Eingabe- oder Ausgabetypen als ein Stream
-Objekt verwendet, müssen Sie eine Serialisierungsbibliothek zu Ihrer Anwendung hinzufügen. Auf diese Weise können Sie die JSON-Eingabe in eine Instanz der von Ihnen definierten Klasse konvertieren. Es gibt zwei Methoden der Serialisierung für C#-Funktionen in Lambda: reflexionsbasierte Serialisierung und quellengenerierte Serialisierung.
Reflexionsbasierte Serialisierung
AWS stellt vorgefertigte Bibliotheken bereit, die Sie schnell zu Ihrer Anwendung hinzufügen können. Diese Bibliotheken implementieren die Serialisierung mithilfe von Reflektion.
-
Amazon.Lambda.Serialization.SystemTextJson
— Im Backend dient dieses PaketSystem.Text.Json
zur Ausführung von Serialisierungsaufgaben. -
Amazon.Lambda.Serialization.Json
— Im Backend dient dieses PaketNewtonsoft.Json
zur Ausführung von Serialisierungsaufgaben.
Sie können auch Ihre eigene Serialisierungsbibliothek erstellen, indem Sie die ILambdaSerializer
-Schnittstelle implementieren; diese ist als Teil der Amazon.Lambda.Core
-Bibliothek verfügbar. Diese Schnittstelle definiert zwei Methoden:
-
T Deserialize<T>(Stream requestStream);
Sie implementieren diese Methode für die Deserialisierung der Anfragenutzlast von der
Invoke
-API in das Objekt, das Ihrem Lambda-Funktions-Handler übergeben wird. -
T Serialize<T>(T response, Stream responseStream);
Sie implementieren diese Methode, um das von Ihrem Lambda-Funktions-Handler zurückgegebene Ergebnis in die Antwort-Nutzlast zu serialisieren, die der
Invoke
-API-Vorgang zurückgibt.
Das Hauptbeispiel auf dieser Seite verwendet reflektionsbasierte Serialisierung. Die reflektionsbasierte Serialisierung ist sofort einsatzbereit AWS Lambda und erfordert keine zusätzliche Einrichtung, weshalb sie aus Gründen der Einfachheit eine gute Wahl ist. Sie erfordert jedoch eine höhere Nutzung des Funktionsspeichers. Aufgrund von Laufzeitreflexionen kann es auch zu höheren Funktionslatenzen kommen.
Von der Quelle generierte Serialisierung
Bei der quellgenerierten Serialisierung wird der Serialisierungscode zur Kompilierzeit generiert. Dadurch entfällt die Notwendigkeit von Überlegungen und die Leistung Ihrer Funktion kann verbessert werden. Um die quellengenerierte Serialisierung in Ihrer Funktion zu verwenden, müssen Sie wie folgt vorgehen:
-
Erstellen Sie eine neue Teilklasse, die von
JsonSerializerContext
erbt, und fügen SieJsonSerializable
-Attribute für alle Typen hinzu, die serialisiert oder deserialisiert werden müssen. -
Konfigurieren Sie das
LambdaSerializer
so, dass es einSourceGeneratorLambdaJsonSerializer<T>
verwendet. -
Aktualisieren Sie alle manuellen Serialisierungen und Deserialisierungen in Ihrem Anwendungscode, um die neu erstellte Klasse zu verwenden.
Das folgende Beispiel zeigt, wie Sie das Hauptbeispiel auf dieser Seite, das reflektionsbasierte Serialisierung verwendet, so ändern können, dass stattdessen die quellgenerierte Serialisierung verwendet wird.
using System.Text.Json;
using System.Text.Json.Serialization;
...
public class Order
{
public string OrderId { get; set; } = string.Empty;
public double Amount { get; set; }
public string Item { get; set; } = string.Empty;
}
[JsonSerializable(typeof(Order))]
public partial class OrderJsonContext : JsonSerializerContext {}
public class OrderHandler
{
...
public async Task<string> HandleRequest(string input, ILambdaContext context)
{
var order = JsonSerializer.Deserialize(input, OrderJsonContext.Default.Order);
...
}
}
Für die quellgenerierte Serialisierung ist mehr Einrichtung erforderlich als für die reflexionsbasierte Serialisierung. Funktionen, die quellgenerierte Daten verwenden, verbrauchen jedoch tendenziell weniger Speicher und weisen aufgrund der Codegenerierung während der Kompilierung eine bessere Leistung auf. Um Kaltstarts von Funktionen zu vermeiden, sollten Sie in Erwägung ziehen, zur quellgenerierten Serialisierung zu wechseln.
Anmerkung
Wenn Sie die native ahead-of-time Kompilierung (AOT) mit Lambda verwenden möchten, müssen Sie die quellengenerierte Serialisierung verwenden.
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 Amazon.Lambda.Core.ILambdaContext
und das zweite Argument der Haupthandlerfunktion.
public async Task<string> HandleRequest(Order order, ILambdaContext context) {
...
}
Das Kontextobjekt ist eine optionale Eingabe. Weitere Hinweise zu gültigen akzeptierten Handler-Signaturen finden Sie unterGültige Handler-Signaturen für C#-Funktionen.
Das Kontextobjekt ist nützlich, um Funktionsprotokolle für Amazon zu erstellen CloudWatch. Sie können 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 die Verarbeitung aus irgendeinem Grund fehlschlägt:
context.Logger.LogError($"Failed to process order: {ex.Message}");
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 C#-Funktionsinformationen.
Verwenden Sie die SDK for .NET Version 3 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 von SDK for .NET v3.
Anmerkung
Die SDK for .NET (v2) ist veraltet. Wir empfehlen, nur Version 3 zu verwenden. SDK for .NET
Mit dem folgenden Amazon.Lambda.Tools
Befehl können Sie Ihrem Projekt SDK-Abhängigkeiten hinzufügen:
dotnet add package
<package_name>
Im Hauptbeispiel auf dieser Seite müssen wir beispielsweise die Amazon S3 S3-API verwenden, um eine Quittung auf S3 hochzuladen. Wir können den Amazon S3 SDK-Client mit dem folgenden Befehl importieren:
dotnet add package AWSSDK.S3
Dieser Befehl fügt die Abhängigkeit zu Ihrem Projekt hinzu. In der .csproj
Datei Ihres Projekts sollten Sie außerdem eine Zeile sehen, die der folgenden ähnelt:
<PackageReference Include="AWSSDK.S3" Version="3.7.2.18" />
Importieren Sie dann die Abhängigkeiten direkt in Ihren C#-Code:
using Amazon.S3;
using Amazon.S3.Model;
Der Beispielcode initialisiert dann einen Amazon S3 S3-Client (unter Verwendung der standardmäßigen Anmeldeinformationsanbieterkette) wie folgt:
private static readonly AmazonS3Client s3Client = new();
In diesem Beispiel haben wir unseren Amazon S3 S3-Client außerhalb der Haupthandlerfunktion initialisiert, um zu vermeiden, dass wir ihn jedes Mal initialisieren müssen, wenn wir unsere Funktion aufrufen. Nachdem Sie Ihren SDK-Client initialisiert haben, können Sie ihn verwenden, um mit anderen Diensten zu interagieren. AWS Der Beispielcode ruft die Amazon S3 PutObject
-API wie folgt auf:
var putRequest = new PutObjectRequest
{
BucketName = bucketName,
Key = key,
ContentBody = receiptContent,
ContentType = "text/plain"
};
await s3Client.PutObjectAsync(putRequest);
Zugriff auf Umgebungsvariablen
In Ihrem Handler-Code können Sie mithilfe der System.Environment.GetEnvironmentVariable
-Methode auf beliebige Umgebungsvariablen verweisen. In diesem Beispiel verweisen wir mit den folgenden Codezeilen auf die definierte RECEIPT_BUCKET
Umgebungsvariable:
string? bucketName = Environment.GetEnvironmentVariable("RECEIPT_BUCKET");
if (string.IsNullOrWhiteSpace(bucketName))
{
throw new ArgumentException("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 wurden, bleiben zwischen Aufrufen im Speicher, sodass Sie sie nicht bei jedem Aufruf Ihrer Funktion neu erstellen müssen.
Im Beispielcode befindet sich der S3-Client-Initialisierungscode außerhalb der Haupthandler-Methode. Die Laufzeit initialisiert den Client, bevor die Funktion ihr erstes Ereignis verarbeitet, was zu längeren Verarbeitungszeiten führen kann. Nachfolgende Ereignisse sind viel schneller, da Lambda den Client nicht erneut initialisieren muss.
Vereinfachen Sie den Funktionscode mit dem Lambda Annotations Framework
Lambda Annotations
Ein Beispiel für eine vollständige Anwendung, die Lambda-Annotationen verwendet, finden Sie im PhotoAssetManagerawsdocs/aws-doc-sdk-examples
GitHub Repository. Die Function.cs
Hauptdatei im PamApiAnnotations
Verzeichnis verwendet Lambda-Anmerkungen. Zum Vergleich: Das PamApi
Verzeichnis enthält äquivalente Dateien, die mit dem regulären Lambda-Programmiermodell geschrieben wurden.
Abhängigkeitsinjektion mit dem Lambda Annotations-Framework
Sie können auch das Lambda Annotations-Framework verwenden, um Ihren Lambda-Funktionen eine Dependency Injection hinzuzufügen, indem Sie die Syntax verwenden, mit der Sie vertraut sind. Wenn Sie einer [LambdaStartup]
-Datei ein Startup.cs
-Attribut hinzufügen, generiert das Lambda Annotations-Framework den erforderlichen Code zur Kompilierzeit.
[LambdaStartup]
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddSingleton<IDatabaseRepository, DatabaseRepository>();
}
}
Ihre Lambda-Funktion kann Dienste entweder durch Konstruktorinjektion oder durch Injektion in einzelne Methoden unter Verwendung des [FromServices]
-Attributs injizieren.
[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))]
namespace GetProductHandler;
public class Function
{
private readonly IDatabaseRepository _repo;
public Function(IDatabaseRepository repo)
{
this._repo = repo;
}
[LambdaFunction]
[HttpApi(LambdaHttpMethod.Get, "/product/{id}")]
public async Task<Product> FunctionHandler([FromServices] IDatabaseRepository repository, string id)
{
return await this._repo.GetById(id);
}
}
Bewährte Codemethoden für C#-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.
-
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. Vermeiden Sie es bei in .NET verfassten Funktionen, die gesamte AWS SDK-Bibliothek als Teil Ihres Bereitstellungspakets hochzuladen. 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 APIs in Ihrem Lambda-Funktionscode nicht undokumentiert, nicht öffentlich. Für AWS Lambda verwaltete Laufzeiten führt Lambda regelmäßig Sicherheits- und Funktionsupdates für interne Lambda-Laufzeiten durch. APIs Diese internen API-Updates können abwärtsinkompatibel sein, was zu unbeabsichtigten Folgen wie Aufruffehlern führen kann, wenn Ihre Funktion von diesen nicht öffentlichen Daten abhängig ist. APIs Eine Liste der öffentlich verfügbaren Programme finden Sie in der API-Referenz. APIs
-
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?
.