Charges de travail .NET sur AWS Lambda

MODULE 3.

Module 3 : .NET sur AWS Lambda

 MODULE D'APPRENTISSAGE

Veuillez noter que vous pouvez suivre les exemples présentés ici, mais ce n'est pas obligatoire.

AWS Lambda prend en charge plusieurs versions de .NET, sur les architectures x86_64 et Arm64 (Graviton2). Vous êtes libre de choisir l'architecture de votre choix. Votre code et votre processus de déploiement ne changent pas.

Lambda étant un service sans serveur, vous ne payez que ce que vous utilisez. Si votre fonction Lambda doit être exécutée plusieurs fois par jour, c'est tout ce que vous payez. Mais parce qu'il peut s'adapter à vos besoins et qu'il peut également démarrer un millier d'instances simultanément !

 Durée

60 minutes 

Tarification

Comme mentionné ci-dessus, vous ne payez que ce que vous utilisez. Le montant que vous payez est calculé en fonction de la durée d'exécution de votre fonction Lambda (arrondie à la milliseconde la plus proche) et de la quantité de mémoire que vous avez allouée à la fonction.

N'oubliez pas que c'est la quantité de mémoire allouée, et non la quantité utilisée lors d'une invocation, qui est utilisée dans le calcul du prix. Il est donc intéressant de tester vos fonctions afin d'évaluer la quantité maximale de mémoire qu'elles utilisent lors d'une invocation. Le fait de limiter la quantité de mémoire allouée au minimum nécessaire permettra de réduire le coût d'utilisation des fonctions Lambda. Consultez cette page sur la tarification d'AWS Lambda pour en savoir plus.

Remarque : si votre fonction Lambda utilise d'autres services tels que S3 ou Kinesis, ces services peuvent également vous être facturés.

Versions prises en charge de .NET

Il existe différentes manières d'exécuter des fichiers binaires .NET sur la plateforme Lambda. La solution la plus courante, et celle à prendre en compte en premier, consiste à utiliser un environnement d'exécution géré fourni par AWS. C'est le moyen le plus simple de démarrer, le plus pratique et le plus performant. Si vous ne souhaitez pas ou ne pouvez pas utiliser le moteur d'exécution géré, deux autres options s'offrent à vous : un environnement d'exécution personnalisé ou une image de conteneur. Les deux options ont leurs propres avantages et inconvénients et seront discutées plus en détail ci-dessous.

Exécutions gérées

Le service AWS Lambda fournit divers environnements d'exécution courants sur lesquels vous pouvez exécuter votre code. En ce qui concerne les environnements d'exécution .NET, AWS maintient le moteur d'exécution à jour et y apporte les correctifs nécessaires avec les dernières versions disponibles auprès de Microsoft. En tant que développeur, vous n'avez rien à faire en ce qui concerne la gestion du moteur d'exécution que votre code utilisera, si ce n'est de spécifier la version que vous souhaitez utiliser dans votre fichier .csproj habituel.

À l'heure actuelle, AWS propose uniquement des environnements d'exécution gérés pour les versions LTS (Long Term Support) de l'exécution .NET, à savoir .NET 3.1 et .NET 6 au moment de la rédaction de cet article. Les environnements d'exécution gérés .NET sont disponibles pour les architectures x86_64 et arm64 et s'exécutent sur Amazon Linux 2. Si vous souhaitez utiliser une version de .NET autre que celles proposées par AWS, vous pouvez créer votre propre environnement d'exécution personnalisé ou créer une image de conteneur adaptée à vos besoins.

Si vous souhaitez sortir du monde .NET, sachez que le service Lambda propose également des environnements d'exécution gérés pour d'autres langages : Node.js, Python, Ruby, Java et Go. Pour plus de détails sur la liste des temps d'exécution gérés et des versions des langues prises en charge, consultez cette page sur les exécutions disponibles.

Exécutions personnalisées

Les environnements d'exécution personnalisés sont des environnements d'exécution que vous créez et regroupez vous-même. Il y a plusieurs raisons pour lesquelles vous feriez cela. La plus courante est que vous souhaitiez utiliser une version .NET qui n'est pas proposée en tant qu'exécutions gérées par le service Lambda. Une autre raison, moins courante, serait que vous souhaitiez avoir un contrôle précis sur les versions mineures et les correctifs d'exécution.

La création de l'environnement d'exécution personnalisé ne demande que très peu d'efforts de votre part. Il vous suffit de faire :

--self-contained true à la commande build.

Cela peut être fait directement avec dotnet build. Vous pouvez également le faire via le fichier aws-lambda-tools-defaults.json avec le paramètre suivant :

« msbuild-parameters » : « --self-contained true »

C'est la seule chose qu'il y ait, un simple indicateur de compilateur lors de la création d'une offre groupée de la fonction Lambda.NET. Le package à déployer contiendra désormais votre code, ainsi que les fichiers requis provenant du moteur d'exécution .NET que vous avez choisi.

C'est maintenant à vous de corriger et de mettre à jour l'exécution comme bon vous semble. La mise à jour du moteur d'exécution nécessite de redéployer la fonction, car le code de la fonction et le moteur d'exécution sont regroupés.

Le package déployé est nettement plus volumineux que l'exécution gérée car il contient tous les fichiers d'exécution nécessaires. Cela affecte négativement les temps de démarrage à froid (nous y reviendrons plus tard). Pour réduire cette taille, pensez à utiliser les fonctionnalités de compilation .NET Trimming et ReadyToRun. Veuillez toutefois lire la documentation relative à ces fonctionnalités avant de le faire.

Vous pouvez créer un environnement d'exécution personnalisé avec n'importe quelle version de .NET exécutée sous Linux. Un cas d'utilisation courant consiste à déployer des fonctions avec les versions « actuelles » ou préliminaires de .NET.

Lorsque vous utilisez des environnements d'exécution personnalisés, vous pouvez utiliser une très grande variété de langages proposés par la communauté. Vous pouvez même créer votre propre environnement d'exécution personnalisé, comme d'autres l'ont fait pour exécuter des langages tels que Erlang et COBOL.

Conteneur d'images

Outre l'exécution gérée et l'exécution personnalisée, le service AWS Lambda vous permet également de regrouper votre code dans une image de conteneur et de déployer cette image sur le service Lambda. Cette option convient aux équipes qui ont investi du temps dans la création et le déploiement de leur code dans des conteneurs, ou à celles qui ont besoin de mieux contrôler le système d'exploitation et l'environnement dans lesquels le code s'exécute. Les images d'une taille maximale de 10 Go sont prises en charge.

AWS fournit une variété d'images de base pour .NET et .NET Core. https://gallery.ecr.aws/lambda/dotnet, elles vous permettront de démarrer très rapidement.

Une autre option consiste à créer une image personnalisée adaptée à votre fonction. Il s'agit d'un cas d'utilisation plus avancé qui nécessite que vous modifiiez le Dockerfile en fonction de vos besoins. Cette approche ne sera pas abordée dans ce cours, mais si vous empruntez cette voie, jetez un œil aux Dockerfiles de ce référentiel : https://github.com/aws/aws-lambda-dotnet/tree/master/LambdaRuntimeDockerfiles/Images.

Notez que la mise à jour de votre fonction Lambda sera plus lente avec les conteneurs en raison de la taille du téléchargement. Les conteneurs présentent également la pire des trois options de démarrage à froid. Plus d'informations à ce sujet plus loin dans le module.

Choisir l'exécution qui vous convient

Si vous souhaitez bénéficier des meilleures performances de démarrage, d'une facilité de déploiement et de prise en main, tout en conservant les versions LTS de .NET, optez pour des environnements d'exécution .NET gérés.

Les images de conteneur constituent une excellente option qui vous permet d'utiliser des images créées par AWS pour différentes versions de .NET. Vous pouvez également choisir votre propre image de conteneur et modifier le système d'exploitation et l'environnement dans lesquels le code s'exécute. Les images de conteneurs conviennent également aux organisations qui utilisent déjà largement les conteneurs.

Si vous avez des exigences très spécifiques concernant les versions de .NET et ses bibliothèques d'exécution, et que vous souhaitez les contrôler vous-même, envisagez d'utiliser un environnement d'exécution personnalisé. Cependant, gardez à l'esprit que c'est à vous de gérer et de corriger le moteur d'exécution. Si Microsoft publie une mise à jour de sécurité, vous devez en être conscient et mettre à jour votre environnement d'exécution personnalisé de manière appropriée. Du point de vue des performances, l'exécution personnalisée est la plus lente des trois à démarrer.

Une fois votre fonction Lambda démarrée, les performances de l'exécution gérée, de l'image du conteneur et de l'exécution personnalisée seront très similaires.

AWS SDK pour .NET

Si vous avez développé des applications .NET qui utilisent les services AWS, vous avez probablement utilisé le kit AWS SDK pour .NET. Le SDK permet aux développeurs .NET d'appeler facilement les services AWS de manière cohérente et familière. Le SDK est mis à jour au fur et à mesure que les services sont publiés ou mis à jour. Le SDK est disponible en téléchargement sur NuGet.

Comme pour de nombreux éléments liés à AWS, le SDK est divisé en packages plus petits, chacun traitant d'un seul service.

Par exemple, si vous souhaitez accéder aux compartiments S3 depuis votre application .NET, vous devez utiliser le package NuGet AWSSDK.S3. Ou si vous souhaitez accéder à DynamoDB depuis votre application .NET, vous pouvez utiliser le package NuGet AWSSDK.DynamoDBv2.

Mais vous n'ajoutez que les packages NuGet dont vous avez besoin. En divisant le SDK en packages plus petits, vous réduisez la taille de votre propre package de déploiement.

Si votre gestionnaire de fonctions Lambda a besoin de recevoir des événements provenant d'autres services AWS, recherchez des packages NuGet spécifiques liés aux événements. Ils contiennent les types pertinents pour gérer les événements. Les packages suivent le modèle de dénomination AWSSDK.Lambda. [SERVICE] Événements.

Par exemple, si votre fonction Lambda est déclenchée par :

événements S3 entrants, utilisez le package AWSSDK.Lambda.S3Events

événements Kinesis entrants, utilisez le package AWSSDK.Lambda.KinesisEvents

notifications SNS entrantes, utilisez le package AWSSDK.Lambda.SNSEvents

messages SQS entrants, utilisez le package AWSSDK.Lambda.SQSEvents

L'utilisation du SDK pour interagir avec les services AWS est très simple. Ajoutez une référence au package NuGet dans votre projet, puis appelez le service comme vous le feriez avec n'importe quelle autre bibliothèque .NET que vous pourriez utiliser.

Le fait que vous utilisiez le SDK à partir d'une fonction Lambda n'a aucune incidence sur la façon dont vous l'utilisez.

N'oubliez pas que vous n'avez pas nécessairement besoin d'ajouter des packages NuGet du SDK AWS à votre projet. Par exemple, si votre fonction Lambda appelle un serveur SQL AWS RDS, vous pouvez simplement utiliser Entity Framework pour accéder à la base de données. Aucune bibliothèque spécifique à AWS supplémentaire n'est requise. Mais si vous souhaitez récupérer un nom d'utilisateur/mot de passe pour la base de données depuis Secrets Manager, vous devez ajouter le package NuGet AWSSDK.SecretsManager.

Remarque sur les autorisations

En règle générale, vous devez utiliser le niveau d'autorisation le plus bas nécessaire pour effectuer une tâche. Tout au long de ce cours, vous serez encouragé et vous apprendrez comment procéder.

Toutefois, pour simplifier l'enseignement de ce cours, nous vous suggérons de faire appel à un utilisateur AWS avec la politique d'AdministratorAccess ci-jointe. Cette politique vous permet de créer les rôles nécessaires au déploiement des fonctions Lambda. Lorsque vous ne travaillez pas sur le cours, vous devez supprimer cette politique pour votre utilisateur AWS.

Une fonction Lambda .NET de Hello World Style

Comme vous l'avez vu dans un module précédent, il est très facile de créer, de déployer et d'invoquer une fonction Lambda .NET. Dans cette section, vous ferez de même, mais plus lentement, et j'expliquerai ce qui se passe à chaque étape. Le code généré et les fichiers de configuration seront discutés.

Création de la fonction

Vous devez installer l'outillage requis pour suivre cette procédure. Veuillez consulter le module 3 pour plus de détails sur la procédure à suivre.

Si vous ne voulez pas vous lancer tout de suite, voici un petit rappel.

Installez les modèles de fonctions Lambda .NET :

dotnet new -i Amazon.Lambda.Templates

Installez les outils .NET pour déployer et gérer les fonctions Lambda :

dotnet tool install -g Amazon.Lambda.Tools

Maintenant que les modèles sont installés, vous pouvez créer une nouvelle fonction

À partir de la ligne de commande, exécutez :

dotnet new lambda.EmptyFunction -n HelloEmptyFunction

Cela crée un nouveau répertoire appelé HelloEmptyFunction. À l'intérieur se trouvent deux autres répertoires, src et test. Comme ses noms l'indiquent, le répertoire src contient le code de la fonction et le répertoire de test contient les tests unitaires de la fonction. Lorsque vous naviguez dans ces répertoires, vous constaterez qu'ils contiennent chacun un autre répertoire. À l'intérieur de ces sous-répertoires se trouvent les fichiers de code de la fonction et les fichiers de tests unitaires.

HelloEmptyFunction
    ├───src
    │   └───HelloEmptyFunction
    │           aws-lambda-tools-defaults.json // The default configuration file
    │           Function.cs // The code for the function
    │           HelloEmptyFunction.csproj // Standard C# project file
    │           Readme.md // A readme file
    │
    └───test
        └───HelloEmptyFunction.Tests
                FunctionTest.cs // The unit tests for the function
                HelloEmptyFunction.Tests.csproj // Standard C# project file

Jetons d'abord un coup d'œil au fichier Function.cs.

using Amazon.Lambda.Core;

// Assembly attribute to enable the Lambda function's JSON input to be converted into a .NET class.
[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))]

namespace HelloEmptyFunction;

public class Function
{
    
    /// <summary>
    /// A simple function that takes a string and does a ToUpper
    /// </summary>
    /// <param name="input"></param>
    /// <param name="context"></param>
    /// <returns></returns>
    public string FunctionHandler(string input, ILambdaContext context)
    {
        return input.ToUpper();
    }
}

Quelques remarques sur les lignes qui nécessitent une petite explication :

La ligne 4 permet de convertir l'entrée JSON en classe .NET.

Ligne 17, l'entrée JSON de la fonction sera convertie en chaîne.

Ligne 17, un objet ILambdaContext est transmis en tant que paramètre. Il peut être utilisé pour la journalisation, la détermination du nom de la fonction, la durée d'exécution de la fonction et d'autres informations.

Comme vous pouvez le constater, le code est très simple et devrait être familier à tous ceux qui ont travaillé avec C#.

Bien que la méthode FunctionHandler soit synchrone, les fonctions Lambda peuvent être asynchrones comme n'importe quelle autre méthode .NET. Tout ce que vous avez à faire est de changer le FunctionHandler en

public async Task<string> FunctionHandler(..)

Jetons un coup d'œil au fichier aws-lambda-tools-defaults.json :

{
  "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": "",
  "region": "",
  "configuration": "Release",
  "function-runtime": "dotnet6",
  "function-memory-size": 256,
  "function-timeout": 30,
  "function-handler": "HelloEmptyFunction::HelloEmptyFunction.Function::FunctionHandler"
}

La ligne 10 précise que la fonction doit être intégrée à la configuration de la version.

La ligne 11 indique au service Lambda l'exécution à utiliser.

La ligne 12 spécifie la quantité de mémoire à allouer à la fonction, dans ce cas 256 Mo.

La ligne 13 spécifie le délai d'expiration de la fonction, dans ce cas 30 secondes. Le délai maximum autorisé est de 15 minutes.

La ligne 14 spécifie le gestionnaire de fonctions. Il s'agit de la méthode qui sera invoquée par le service Lambda lorsque cette fonction sera appelée.

Le gestionnaire de fonctions est composé de trois parties :

« AssemblyName::Namespace.ClassName::MethodName »

Un peu plus tard, vous allez créer et déployer cette fonction sur le service AWS Lambda à l'aide de la configuration de ce fichier.

Mais d'abord, jetons un coup d'œil au projet de test et à son fichier HelloEmptyFunction.tests.cs :

using Xunit;
using Amazon.Lambda.Core;
using Amazon.Lambda.TestUtilities;

namespace HelloEmptyFunction.Tests;

public class FunctionTest
{
    [Fact]
    public void TestToUpperFunction()
    {

        // Invoke the lambda function and confirm the string was upper cased.
        var function = new Function();
        var context = new TestLambdaContext();
        var upperCase = function.FunctionHandler("hello world", context);

        Assert.Equal("HELLO WORLD", upperCase);
    }
}

Le code ici est relativement simple et utilise le framework de test xUnit. Vous pouvez tester vos fonctions Lambda comme vous le feriez pour n'importe quelle autre méthode.

La ligne 14 crée une nouvelle instance de la classe fonction.

La ligne 15 crée une nouvelle instance de la classe TestLambdaContext, qui sera transmise à la fonction Lambda sur la ligne suivante.

La ligne 16 invoque la méthode FunctionHandler sur la fonction en lui transmettant la chaîne « hello world » et le contexte. Il enregistre la réponse dans la variable upperCase.

La ligne 18 affirme que la variable upperCase est égale à « HELLO WORLD ».

Vous pouvez exécuter ce test depuis la ligne de commande ou depuis votre IDE préféré. D'autres types de tests peuvent être effectués sur les fonctions Lambda. Si vous souhaitez en savoir plus à ce sujet, consultez un module ultérieur dans lequel vous découvrirez différentes manières de tester et de déboguer vos fonctions Lambda.

Déploiement de la fonction

Maintenant que vous disposez d'une fonction Lambda et que vous avez peut-être effectué un test unitaire, il est temps de déployer la fonction Lambda sur le service AWS Lambda.

À partir de la ligne de commande, accédez au répertoire contenant le fichier HelloEmptyFunction.csproj et exécutez la commande suivante :

dotnet lambda deploy-function HelloEmptyFunction  

Vous verrez une sortie qui inclut les éléments suivants (je l'ai découpée pour plus de clarté) –

... dotnet publish --output "C:\dev\Lambda_Course_Samples\HelloEmptyFunction\src\HelloEmptyFunction\bin\Release\net6.0\publish" --configuration "Release" --framework "net6.0" /p:GenerateRuntimeConfigurationFiles=true --runtime linux-x64 --self-contained false
Zipping publish folder C:\dev\Lambda_Course_Samples\HelloEmptyFunction\src\HelloEmptyFunction\bin\Release\net6.0\publish to C:\dev\Lambda_Course_Samples\HelloEmptyFunction\src\HelloEmptyFunction\bin\Release\net6.0\HelloEmptyFunction.zip
... zipping: Amazon.Lambda.Core.dll
... zipping: Amazon.Lambda.Serialization.SystemTextJson.dll
... zipping: HelloEmptyFunction.deps.json
... zipping: HelloEmptyFunction.dll
... zipping: HelloEmptyFunction.pdb
... zipping: HelloEmptyFunction.runtimeconfig.json
Created publish archive (C:\dev\Lambda_Course_Samples\HelloEmptyFunction\src\HelloEmptyFunction\bin\Release\net6.0\HelloEmptyFunction.zip).

La ligne 1 compile et publie le projet. Notez que le moteur d'exécution est linux-x64 et que l'indicateur autonome est false (ce qui signifie que la fonction utilisera un environnement d'exécution .NET géré sur le service Lambda, par opposition à un environnement d'exécution personnalisé).

La ligne 2 compresse le projet publié dans un fichier zip.

Les lignes 3 à 8 indiquent les fichiers en cours de compression.

La ligne 9 confirme que le fichier zip a été créé.

Ensuite, il vous sera demandé « Sélectionnez le rôle IAM qui doit fournir des informations d'identification AWS à votre code : ». Une liste des rôles que vous avez créés précédemment peut vous être présentée, mais au bas de la liste se trouve l'option « *** Créer un nouveau rôle IAM *** », saisissez ce numéro à côté de cette option.

Il vous sera demandé de « saisir le nom du nouveau rôle IAM : ». Tapez « HelloEmptyFunctionRole ».

Il vous sera ensuite demandé de « sélectionner la politique IAM à associer au nouveau rôle et d'accorder des autorisations » et une liste de politiques sera présentée. Cela ressemblera à la liste ci-dessous, mais le vôtre est peut-être plus long –

1) AWSLambdaReplicator (Grants Lambda Replicator necessary permissions to replicate functions ...)
2) AWSLambdaDynamoDBExecutionRole (Provides list and read access to DynamoDB streams and writ ...)
3) AWSLambdaExecute (Provides Put, Get access to S3 and full access to CloudWatch Logs.)
4) AWSLambdaSQSQueueExecutionRole (Provides receive message, delete message, and read attribu ...)
5) AWSLambdaKinesisExecutionRole (Provides list and read access to Kinesis streams and write  ...)
6) AWSLambdaBasicExecutionRole (Provides write permissions to CloudWatch Logs.)
7) AWSLambdaInvocation-DynamoDB (Provides read access to DynamoDB Streams.)
8) AWSLambdaVPCAccessExecutionRole (Provides minimum permissions for a Lambda function to exe ...)
9) AWSLambdaRole (Default policy for AWS Lambda service role.)
10) AWSLambdaENIManagementAccess (Provides minimum permissions for a Lambda function to manage ...)
11) AWSLambdaMSKExecutionRole (Provides permissions required to access MSK Cluster within a VP ...)
12) AWSLambda_ReadOnlyAccess (Grants read-only access to AWS Lambda service, AWS Lambda consol ...)
13) AWSLambda_FullAccess (Grants full access to AWS Lambda service, AWS Lambda console feature ...) 

Sélectionnez « AWSLambdaBasicExecutionRole », c'est le numéro 6 sur ma liste.

Au bout d'un moment, vous verrez –

Waiting for new IAM Role to propagate to AWS regions
...............  Done
New Lambda function created

Vous pouvez maintenant invoquer la fonction.

Invocation de la fonction

Ligne de commande

Vous pouvez utiliser l'outil dotnet lambda pour invoquer la fonction depuis le shell de votre choix :

dotnet lambda invoke-function HelloEmptyFunction --payload "Invoking a Lambda function"

Pour les fonctions Lambda simples comme celles ci-dessus, il n'y a pas de code JSON à échapper, mais lorsque vous souhaitez transmettre du JSON qui doit être désérialisé, la charge utile qui sort varie en fonction du shell que vous utilisez.

Vous verrez une sortie qui ressemble à ce qui suit :

Amazon Lambda Tools for .NET Core applications (5.4.1)
Project Home: https://github.com/aws/aws-extensions-for-dotnet-cli, https://github.com/aws/aws-lambda-dotnet

Payload:
"INVOKING A LAMBDA FUNCTION"

Log Tail:
START RequestId: 3d43c8be-8eca-48a1-9e51-96d9c84947b2 Version: $LATEST
END RequestId: 3d43c8be-8eca-48a1-9e51-96d9c84947b2
REPORT RequestId: 3d43c8be-8eca-48a1-9e51-96d9c84947b2  Duration: 244.83 ms      Billed Duration: 245 ms                                                                                                                  
Memory Size: 256 MB      Max Memory Used: 68 MB      Init Duration: 314.32 ms

La sortie « Payload : » est la réponse de la fonction Lambda.

Notez que le journal contient des informations utiles sur l'invocation de la fonction Lambda, comme sa durée d'exécution et la quantité de mémoire utilisée. Pour une fonction simple comme celle-ci, 244,83 ms peuvent sembler beaucoup, mais c'était la première fois que la fonction était invoquée, ce qui signifie que plus de travail devait être effectué et que les invocations suivantes auraient été plus rapides. Consultez la section sur les démarrages à froid pour plus d'informations.

Apportons une petite modification au code pour ajouter certaines de nos propres instructions de journal.

Ajoutez ce qui suit au-dessus de l'instruction de retour dans la méthode FunctionHandler :

context.Logger.LogInformation("Input: " + input);

Déployez à nouveau à l’aide de :

dotnet lambda deploy-function HelloEmptyFunction

Cette fois, il n'y aura aucune question sur le rôle ou les autorisations.

Une fois la fonction déployée, vous pouvez l'invoquer à nouveau.

dotnet lambda invoke-function HelloEmptyFunction --payload "Invoking a Lambda function" 

Cette fois, la sortie contiendra une instruction de journal supplémentaire.

Payload:
"INVOKING A LAMBDA FUNCTION"

Log Tail:
START RequestId: 7f77a371-c183-494f-bb44-883fe0c57471 Version: $LATEST
2022-06-03T15:36:20.238Z        7f77a371-c183-494f-bb44-883fe0c57471    info    Input: Invoking a Lambda function
END RequestId: 7f77a371-c183-494f-bb44-883fe0c57471
REPORT RequestId: 7f77a371-c183-494f-bb44-883fe0c57471  Duration: 457.22 ms     Billed Duration: 458 ms                                                                                                       
Memory Size: 256 MB      Max Memory Used: 62 MB  Init Duration: 262.12 ms

À la ligne 6, se trouve l'instruction du journal. Les journaux des fonctions Lambda sont également écrits dans les journaux CloudWatch (à condition que vous ayez autorisé la fonction Lambda à le faire).

Console AWS

Vous pouvez également invoquer la fonction à partir de la console AWS.

Connectez-vous à la console AWS et sélectionnez la fonction Lambda que vous souhaitez invoquer.

Cliquez sur l'onglet Test.

Faites défiler la page jusqu'à la section Event JSON et saisissez « Invoquer une fonction Lambda », y compris les guillemets.

Cliquez ensuite sur le bouton Test.

Vous verrez une sortie semblable à ce qui suit.

Notez que la sortie du journal est également visible.

Une fonction Lambda .NET qui prend une charge utile JSON

L'exemple précédent était une fonction simple qui prenait une chaîne et renvoyait une chaîne. C'est un bon exemple pour commencer.

Mais vous souhaiterez probablement envoyer des charges utiles JSON aux fonctions Lambda. En fait, si un autre service AWS invoque votre fonction Lambda, il enverra une charge utile JSON. Ces charges utiles JSON sont souvent assez complexes, mais un modèle pour la charge utile sera disponible auprès de NuGet. Par exemple, si vous gérez des événements Kinesis avec votre fonction Lambda, le package Amazon.Lambda.KinesisEvents possède un modèle KinesisEvent. Il en va de même pour les événements S3, les événements SQS, etc.

Plutôt que d'utiliser l'un de ces modèles dès maintenant, vous allez invoquer une nouvelle fonction Lambda avec une charge utile qui représente une personne.

{
  "FirstName": "Alan",
  "LastName": "Adams"
}

La classe C# appropriée pour désérialiser la charge utile JSON est la suivante :

public class Person 
{
    public string FirstName { get; init; }
    public string LastName { get; init; }  
}

Créez la fonction

Comme précédemment, créez une nouvelle fonction à l'aide de la commande suivante :

dotnet new lambda.EmptyFunction -n HelloPersonFunction

Modifiez la fonction

Accédez au fichier Function.cs dans HelloPersonFunction/src/HelloPersonFunction.

Modifiez le code de la méthode FunctionHandler pour qu'il ressemble à ceci :
public string FunctionHandler(Person input, ILambdaContext context)
{
    return $"Hello, {input.FirstName} {input.LastName}";
}
Au bas du fichier, ajoutez une nouvelle classe :
public class Person 
{
    public string FirstName { get; init; }
    public string LastName { get; init; }  
}

Il s'agit de la même commande que celle que vous avez utilisée il y a quelques minutes :

Il s'agit de la même commande que celle que vous avez utilisée il y a quelques minutes :
dotnet lambda deploy-function HelloPersonFunction

Invoquer la fonction

Ligne de commande
 

Votre fonction Lambda peut désormais prendre une charge utile JSON, mais la manière dont vous l'invoquez dépend du shell que vous utilisez en raison de la manière dont le JSON est échappé dans chaque shell.

Si vous utilisez PowerShell ou bash, utilisez :

dotnet lambda invoke-function HelloPersonFunction --payload '{ \"FirstName\": \"Alan\", \"LastName\": \"Adams\" }'
Mais si vous utilisez l'invite de commande Windows, utilisez :
dotnet lambda invoke-function HelloPersonFunction --payload "{ \"FirstName\": \"Alan\", \"LastName\": \"Adams\" }"
Il ne s'agit que d'un simple exemple. Mais, bien entendu, le JSON peut être aussi complexe que nécessaire.
Console AWS
 
Vous pouvez également invoquer la fonction à partir de la console AWS.

Connectez-vous à la console AWS et sélectionnez la fonction Lambda que vous souhaitez invoquer.
Cliquez sur l'onglet Test.
Faites défiler la page jusqu'à la section JSON de l'événement et saisissez :
{
  "FirstName": "Alan",
  "LastName": "Adams"
}
Cliquez ensuite sur le bouton Test.

Vous verrez une sortie semblable à ce qui suit.
Ces derniers exemples sont assez simples et la fonction Lambda n'a utilisé aucun autre service AWS, mais ils constituent un excellent moyen de démarrer et de se familiariser avec le service AWS Lambda, en écrivant des fonctions Lambda, en déployant des packages compilés et en invoquant les fonctions.

Dans la section suivante, vous allez voir comment déployer une fonction Lambda qui répond aux requêtes HTTP.

Création et exécution d'une application API Web en tant que fonction Lambda

Dans les exemples précédents, les fonctions Lambda étaient toutes invoquées via la ligne de commande ou dans la fonctionnalité de test du service Lambda dans la console AWS.

Mais vous pouvez également invoquer la fonction Lambda via une requête HTTP, et c'est un cas d'utilisation très courant.

Les outils AWS pour .NET proposent quelques modèles que vous pouvez utiliser pour créer une fonction Lambda simple hébergeant une application API Web.

Le modèle le plus connu est probablement le modèle Serverless.AspNetCoreWebAPI, qui crée une application API Web simple qui peut être invoquée via une requête HTTP. Le modèle de projet inclut un modèle de configuration CloudFormation qui crée un API Gateway qui transmet les requêtes HTTP à la fonction Lambda.

Lorsqu'elle est déployée sur AWS Lambda, l'API Gateway traduit la requête HTTP en un événement API Gateway et envoie ce JSON à la fonction Lambda. Aucun serveur Kestrel n'est exécuté dans la fonction Lambda lorsqu'elle est déployée sur le service Lambda.

Mais lorsque vous l'exécutez localement, un serveur Web Kestrel démarre, ce qui vous permet d'écrire votre code et de le tester très facilement, comme vous le feriez avec n'importe quelle application d'API Web. Vous pouvez même effectuer le débogage normal ligne par ligne. Vous bénéficiez ainsi du meilleur des deux systèmes !

Créez la fonction

À partir de la ligne de commande, exécutez la commande suivante :
dotnet new serverless.AspNetCoreWebAPI -n HelloAspNetCoreWebAPI
Cela crée un nouveau répertoire appelé HelloAspNetCoreWebAPI. À l'intérieur se trouvent deux autres répertoires, src et test. Comme ses noms l'indiquent, le répertoire src contient le code de la fonction et le répertoire de test contient les tests unitaires de la fonction. Lorsque vous naviguez dans ces répertoires, vous constaterez qu'ils contiennent chacun un autre répertoire. À l'intérieur de ces sous-répertoires se trouvent les fichiers de code de la fonction et les fichiers de tests unitaires.
├───src
│   └───AspNetCoreWebAPI
│       │   appsettings.Development.json
│       │   appsettings.json
│       │   AspNetCoreWebAPI.csproj
│       │   aws-lambda-tools-defaults.json // basic Lambda function config, and points to serverless.template file for deployment
│       │   LambdaEntryPoint.cs // Contains the function handler method, this handles the incoming JSON payload
│       │   LocalEntryPoint.cs // Equivalent to Program.cs when running locally, starts Kestrel (only locally)
│       │   Readme.md  
│       │   serverless.template // CloudFormation template for deployment
│       │   Startup.cs // Familiar Startup.cs, can use dependency injection, read config, etc.
│       │
│       └───Controllers
│               ValuesController.cs // Familiar API controller
│
└───test
    └───AspNetCoreWebAPI.Tests
        │   appsettings.json
        │   AspNetCoreWebAPI.Tests.csproj
        │   ValuesControllerTests.cs // Unit test for ValuesController
        │
        └───SampleRequests
                ValuesController-Get.json // JSON representing an APIGatewayProxyRequest, used by the unit test

Déployez la fonction

Le déploiement d'une fonction basée sur un modèle sans serveur.* est un peu plus complexe que le déploiement d'une fonction basée sur un modèle lambda.*.

Avant de tenter de déployer la fonction sans serveur, vous avez besoin d'un compartiment S3. Cela sera utilisé par les outils de déploiement pour stocker une pile CloudFormation.

Vous pouvez utiliser un compartiment S3 existant ou, si vous n'en avez pas, suivre les instructions ci-dessous.
Création du compartiment S3
 
Si vous utilisez la région us-east-1, vous pouvez utiliser la commande suivante pour créer le compartiment :
aws s3api create-bucket --bucket your-unique-bucket-name1234 
Ou si vous utilisez une autre région
aws s3api create-bucket --bucket your-unique-bucket-name1234 --create-bucket-configuration LocationConstraint=REGION
J'ai créé un compartiment dans us-east-1, nommé lambda-course-2022.
aws s3api create-bucket --bucket lambda-course-2022 
Revenir au déploiement de la fonction
 
Maintenant que vous avez un S3, vous pouvez exécuter la commande de déploiement :
dotnet lambda deploy-serverless
Il vous sera demandé de saisir le nom de la pile CloudFormation.
Enter CloudFormation Stack Name: (CloudFormation stack name for an AWS Serverless application)
Tapez AspNetCoreWebAPI

Il vous sera ensuite demandé le nom du compartiment S3. Utilisez le nom du compartiment que vous avez créé précédemment ou un compartiment existant que vous souhaitez utiliser à cette fin.

Une fois que vous l'avez saisi, le processus de génération et de déploiement commence.

Cela prendra plus de temps que les exemples utilisant les modèles de projet lambda.* car il y a plus d'infrastructures à créer et à connecter.

La sortie sera divisée en deux sections distinctes.

La section supérieure sera similaire à celle que vous avez vue lors du déploiement des fonctions précédemment : une publication et un zip du projet, mais cette fois, l'artefact est téléchargé sur S3.
..snip
... zipping: AspNetCoreWebAPI.runtimeconfig.json
... zipping: aws-lambda-tools-defaults.json
Created publish archive (C:\Users\someuser\AppData\Local\Temp\AspNetCoreFunction-CodeUri-Or-ImageUri-637907144179228995.zip).
Lambda project successfully packaged: C:\Users\ someuser\AppData\Local\Temp\AspNetCoreFunction-CodeUri-Or-ImageUri-637907144179228995.zip
Uploading to S3. (Bucket: lambda-course-2022 Key: AspNetCoreWebAPI/AspNetCoreFunction-CodeUri-Or-ImageUri-637907144179228995-637907144208759417.zip)
... Progress: 100%
Ensuite, la pile CloudFormation est créée et toutes les ressources requises sont déployées.
Uploading to S3. (Bucket: lambda-course-2022 Key: AspNetCoreWebAPI/AspNetCoreWebAPI-serverless-637907144211067892.template)
... Progress: 100%
Found existing stack: False
CloudFormation change set created
... Waiting for change set to be reviewed
Created CloudFormation stack AspNetCoreWebAPI

Timestamp            Logical Resource Id                      Status
-------------------- ---------------------------------------- ---------------------------------------- 
6/10/2022 09:53 AM   AspNetCoreWebAPI                         CREATE_IN_PROGRESS
6/10/2022 09:53 AM   AspNetCoreFunctionRole                   CREATE_IN_PROGRESS
6/10/2022 09:53 AM   AspNetCoreFunctionRole                   CREATE_IN_PROGRESS
6/10/2022 09:54 AM   AspNetCoreFunctionRole                   CREATE_COMPLETE
6/10/2022 09:54 AM   AspNetCoreFunction                       CREATE_IN_PROGRESS
6/10/2022 09:54 AM   AspNetCoreFunction                       CREATE_IN_PROGRESS
6/10/2022 09:54 AM   AspNetCoreFunction                       CREATE_COMPLETE
6/10/2022 09:54 AM   ServerlessRestApi                        CREATE_IN_PROGRESS
6/10/2022 09:54 AM   ServerlessRestApi                        CREATE_IN_PROGRESS
6/10/2022 09:54 AM   ServerlessRestApi                        CREATE_COMPLETE
6/10/2022 09:54 AM   ServerlessRestApiDeploymentcfb7a37fc3    CREATE_IN_PROGRESS
6/10/2022 09:54 AM   AspNetCoreFunctionProxyResourcePermissionProd CREATE_IN_PROGRESS
6/10/2022 09:54 AM   AspNetCoreFunctionRootResourcePermissionProd CREATE_IN_PROGRESS
6/10/2022 09:54 AM   AspNetCoreFunctionProxyResourcePermissionProd CREATE_IN_PROGRESS
6/10/2022 09:54 AM   AspNetCoreFunctionRootResourcePermissionProd CREATE_IN_PROGRESS
6/10/2022 09:54 AM   ServerlessRestApiDeploymentcfb7a37fc3    CREATE_IN_PROGRESS
6/10/2022 09:54 AM   ServerlessRestApiDeploymentcfb7a37fc3    CREATE_COMPLETE
6/10/2022 09:54 AM   ServerlessRestApiProdStage               CREATE_IN_PROGRESS
6/10/2022 09:54 AM   ServerlessRestApiProdStage               CREATE_IN_PROGRESS
6/10/2022 09:54 AM   ServerlessRestApiProdStage               CREATE_COMPLETE
6/10/2022 09:54 AM   AspNetCoreFunctionProxyResourcePermissionProd CREATE_COMPLETE
6/10/2022 09:54 AM   AspNetCoreFunctionRootResourcePermissionProd CREATE_COMPLETE
6/10/2022 09:54 AM   AspNetCoreWebAPI                         CREATE_COMPLETE
Stack finished updating with status: CREATE_COMPLETE

Output Name                    Value
------------------------------ --------------------------------------------------
ApiURL                         https://xxxxxxxxx.execute-api.us-east-1.amazonaws.com/Prod/

Tout en bas se trouve l'URL publique que vous pouvez utiliser pour invoquer l'API.

Invocation de la fonction

En ouvrant cette URL dans votre navigateur, ou Fiddler/Postman, etc., vous verrez une réponse du type « Bienvenue dans l'exécution d'ASP.NET Core sur AWS Lambda ».

Essayez ensuite d'ouvrir https://xxxxxxxx.execute-api.us-east-1.amazonaws.com/Prod/api/values, vous invoquerez la méthode GET du contrôleur de valeurs, comme vous le feriez dans une application API Web normale.

Notez que lorsque vous utilisez un API Gateway, la passerelle impose son propre délai d'attente de 29 secondes. Si votre fonction Lambda s'exécute plus longtemps, vous ne recevrez pas de réponse.

Si cela vous intéresse, il existe plusieurs manières de consulter les ressources qui ont été créées.

Pour consulter les ressources AWS créées, vous pouvez utiliser :
aws cloudformation describe-stack-resources --stack-name AspNetCoreWebAPI
Cela vous donnera des détails sur chaque ressource de la pile.

Si vous souhaitez obtenir une sortie plus succincte, utilisez :
aws cloudformation describe-stack-resources --stack-name AspNetCoreWebAPI --query 'StackResources[].[{ResourceType:ResourceType, LogicalResourceId:LogicalResourceId, PhysicalResourceId:PhysicalResourceId}]'
Une autre méthode consiste à ouvrir la console AWS et à accéder au service Lambda. Sur la gauche de l'écran, sélectionnez Application (au lieu de fonctions).


Vous verrez l'application que vous avez créée. Sélectionnez-la, puis faites défiler la page qui s'ouvre vers le bas. Vous verrez toutes les ressources qui ont été créées ici.
Vous avez maintenant vu trois exemples de fonctions Lambda : le premier était un simple Hello World utilisant une chaîne, le second était également très simple mais utilisait un objet JSON, et le troisième était un peu plus complexe, tout en restant très facile à créer et à déployer.

Ces exemples vous permettent de créer et de déployer vos propres fonctions Lambda. Et vous en avez peut-être appris un peu plus sur la façon dont les fonctions Lambda .NET sont invoquées. C'est l'objet de la section suivante.

Les URL de fonction : une alternative aux passerelles d'API

Si tout ce dont vous avez besoin est une fonction Lambda qui répond à une simple requête HTTP, vous devriez envisager d'utiliser les URL des fonctions Lambda.

Ils vous permettent d'attribuer un point de terminaison HTTPS à une fonction Lambda. Vous invoquez ensuite la fonction Lambda en envoyant une requête au point de terminaison HTTPS. Pour plus d'informations, lisez cet article de blog etces documents.

Nettoyer les ressources que vous avez créées

Pour supprimer les fonction Lambda, exécutez :
dotnet lambda delete-function HelloEmptyFunction  
dotnet lambda delete-function HelloPersonFunction

Notez que les commandes ci-dessus ne suppriment pas le rôle que vous avez créé.

Pour supprimer la fonction Lambda qui hébergeait l'application API Web et toutes les ressources associées, exécutez :

dotnet lambda delete-serverless AspNetCoreWebAPI

Comment une fonction .NET Lambda est invoquée

Comme vous pouvez le voir dans les exemples ci-dessus, vous pouvez invoquer une fonction Lambda .NET à l'aide d'une chaîne simple, d'un objet JSON et d'une requête HTTP. Les fonctions Lambda peuvent également être invoquées par d'autres services tels que S3 (lorsqu'un changement de fichier se produit), Kinesis (lorsqu'un événement arrive), DynamoDB (lorsqu'un changement se produit sur une table), SMS (lorsqu'un message arrive), Step Functions, etc.

Comment une fonction Lambda gère-t-elle toutes ces différentes manières d'être invoquée ?

En principe, ces fonctions Lambda sont invoquées lorsque le service Lambda exécute le gestionnaire de fonctions et lui transmet une entrée JSON. Si vous regardez le fichier aws-lambda-tools-defaults.json, vous pouvez voir le « gestionnaire de fonctions » : spécifié. Pour les fonctions Lambda .NET, le gestionnaire comprend « AssemblyName::Namespace.ClassName::MethodName ».

Les fonctions Lambda peuvent également être invoquées en leur transmettant un flux, mais ce scénario est moins courant, consultez la page sur la gestion des flux pour en savoir plus.

Chaque fonction Lambda possède un gestionnaire de fonctions unique.

En plus de l'entrée JSON, le gestionnaire de fonction Lambda peut également accepter un objet ILambdaContext facultatif. Cela vous donne accès à des informations sur l'invocation en cours, telles que le temps qu'il lui reste pour terminer, le nom et la version de la fonction. Vous pouvez également écrire des messages de journal dans l'objet ILambdaContext.

Tous les événements sont au format JSON

Ce qui permet à un service AWS d'invoquer très facilement une fonction Lambda .NET, c'est que ces services émettent du JSON et, comme indiqué ci-dessus, la fonction Lambda .NET accepte les entrées JSON. Les événements déclenchés par les différents services produisent tous un JSON de forme différente, mais les packages AWS Lambda Event NuGet incluent tous les types d'objets pertinents nécessaires pour sérialiser à nouveau le JSON en un objet avec lequel vous pouvez travailler.

Consultez https://www.nuget.org/packages?packagetype=&sortby=relevance&q=Amazon.Lambda&prerel=True pour une liste des packages Lambda disponibles. Vous devrez rechercher dans ces résultats le type d'événement qui vous intéresse.

Par exemple, si vous souhaitez déclencher une fonction Lambda en réponse à une modification de fichier sur un compartiment S3, vous devez créer une fonction Lambda qui accepte un objet de type S3Event. Vous ajoutez ensuite le package Amazon.Lambda.S3Events à votre projet. Modifiez ensuite la méthode du gestionnaire de fonctions en :

public async string FunctionHandler(S3Event s3Event, ILambdaContext context)
{
    ...
}

C'est tout ce dont vous avez besoin pour gérer l'événement S3, vous pouvez examiner l'événement par programmation, voir quelle action a été effectuée sur le fichier, dans quel compartiment il se trouvait, etc. L'Amazon.Lambda.S3Events vous permet de travailler avec l'événement, et non avec S3 lui-même. Si vous souhaitez interagir avec le service S3, vous devez également ajouter le package NuGet AWSSDK.S3 à votre projet. Un module ultérieur abordera le sujet des services AWS invoquant des fonctions Lambda.

Les autres types d'événements suivent le même schéma : ajoutez le package NuGet, modifiez le paramètre dans le gestionnaire de fonctions, puis vous pouvez travailler avec l'objet événement.

Voici quelques-uns des packages courants que vous pouvez utiliser pour gérer les événements provenant d'autres services –

https://www.nuget.org/packages/Amazon.Lambda.SNSEvents

https://www.nuget.org/packages/Amazon.Lambda.DynamoDBEvents

https://www.nuget.org/packages/Amazon.Lambda.CloudWatchEvents

https://www.nuget.org/packages/Amazon.Lambda.KinesisEvents

https://www.nuget.org/packages/Amazon.Lambda.APIGatewayEvents

Vous n'êtes pas limité à l'utilisation des types d'événements définis par AWS lorsque vous appelez une fonction Lambda. Vous pouvez créer vous-même n'importe quel type d'événement. N'oubliez pas que la fonction Lambda peut prendre n'importe quel JSON que vous lui envoyez

Comment se déroule la sérialisation

Vous vous souviendrez qu'il existe deux grandes catégories de modèles de projet Lambda, ceux qui commencent par « lambda ». et ceux qui commencent par « sans serveur ».

Dans le cas des modèles « lambda », il y a un attribut d'assemblage en haut du fichier Function.cs, qui prend en charge la désérialisation de l'événement entrant dans le type .NET de votre gestionnaire de fonctions. Le fichier .csproj contient une référence au package Amazon.Lambda.Serialization.SystemTextJson.
[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))]
Vous n'avez rien d'autre à faire.

Pour les modèles « sans serveur », cela fonctionne un peu différemment.

Le gestionnaire de fonctions est spécifié dans le fichier serverless.template. Si vous déployez une application Serverless.AspNetCoreWebAPI, recherchez la valeur sous Resources.AspNetCoreFunction.Properties.Handler. Le gestionnaire pour ce type de projet se terminera sous la forme suivante : Assembly::Namespace.LambdaEntryPoint::FunctionHandlerAsync.

La classe LambdaEntryPoint fera partie de votre projet et hérite d'une classe dotée d'une méthode FunctionHandlerAsync.

Le gestionnaire de fonctions peut être configuré pour gérer quatre types d'événements différents : une API Gateway REST API, une charge utile API Gateway HTTP API version 1.0, une charge utile API Gateway HTTP API version 2.0 et un Application Load Balancer.

En modifiant la classe dont LambdaEntryPoint hérite, vous pouvez modifier le type d'événement JSON géré par le gestionnaire de fonctions.

Même s'il semble que la fonction Lambda répond à une requête HTTP que vous lui envoyez, avec le JSON que vous définissez, ce n'est pas le cas. En réalité, votre requête HTTP est gérée par une passerelle ou un équilibreur de charge, qui crée ensuite un événement JSON qui est envoyé à votre gestionnaire de fonctions. Cet événement JSON contiendra les données initialement incluses dans la requête HTTP, y compris l'adresse IP source et les en-têtes de demande.

Simultanéité

Il existe deux types de simultanéité à prendre en compte lorsque vous utilisez des fonctions Lambda : la simultanéité réservée et la simultanéité provisionnée.

Un compte AWS possède une limite maximale par défaut quant au nombre d'exécutions Lambda simultanées. Au moment d'écrire ces lignes, cette limite est de 1 000.

Lorsque vous spécifiez une concurrence réservée pour une fonction, vous garantissez que la fonction pourra atteindre le nombre spécifié d'exécutions simultanées. Par exemple, si votre fonction possède une simultanéité réservée de 200, vous vous assurez qu'elle pourra atteindre 200 exécutions simultanées. Notez que cela laisse 800 exécutions simultanées pour les autres fonctions (1000-200 = 800).

Lorsque vous spécifiez la simultanéité provisionnée, vous initialisez un certain nombre d'environnements d'exécution Lambda. Une fois celles-ci initialisées, la fonction Lambda sera en mesure de répondre immédiatement aux demandes, évitant ainsi le problème des « démarrages à froid ». Toutefois, des frais sont associés à l'utilisation de la concurrence provisionnée.

Pour plus d'informations, voir Gestion de la concurrence réservée Lambda et Gestion de la concurrence provisionnée Lambda.

Démarrages à froid et démarrages à chaud

Avant que votre fonction Lambda puisse être invoquée, un environnement d'exécution doit être initialisé, ce qui est fait en votre nom par le service Lambda. Votre code source est téléchargé depuis un compartiment S3 géré par AWS (pour les fonctions qui utilisent des environnements d'exécution gérés et des environnements d'exécution personnalisés) ou depuis un registre de conteneurs Elastic (pour les fonctions qui utilisent des images de conteneur).

La première fois que votre fonction s'exécute, votre code doit être JITed et le code d'initialisation est exécuté (par exemple, votre constructeur). Cela augmente le temps de démarrage à froid.

Si votre fonction est invoquée régulièrement, elle restera « chaude », c'est-à-dire que l'environnement d'exécution sera maintenu. Les invocations ultérieures de la fonction ne seront pas affectées par le temps de démarrage à froid. Les « démarrages à chaud » sont nettement plus rapides que les « démarrages à froid ».

Si votre fonction n'est pas invoquée pendant un certain temps (l'heure exacte n'est pas spécifiée par le service Lambda), l'environnement d'exécution est supprimé. La prochaine invocation de la fonction entraînera à nouveau un démarrage à froid.

Si vous chargez une nouvelle version du code de fonction, la prochaine invocation de la fonction entraînera un démarrage à froid.

Les trois options d'exécution de .NET sur Lambda, d'exécution gérée, d'exécution personnalisée et d'hébergement de conteneurs ont chacune des profils de démarrage à froid différents. Le plus lent est le conteneur, le second plus lent est l'exécution personnalisée et le plus rapide est l'exécution gérée. Dans la mesure du possible, vous devez toujours opter pour l'exécution gérée lorsque vous exécutez des fonctions Lambda .NET.

Il a été constaté que les démarrages à froid sont plus fréquents dans les environnements de test ou de développement que dans les environnements de production. Selon une analyse AWS, les démarrages à froid surviennent dans moins de 1 % des invocations.

Si vous avez une fonction Lambda en production qui n'est que rarement utilisée, mais qui doit répondre rapidement à une demande, et que vous souhaitez éviter les démarrages à froid, vous pouvez utiliser la simultanéité provisionnée ou utiliser un mécanisme permettant d'envoyer un « ping » fréquent à votre fonction afin de la maintenir au chaud.

Si vous souhaitez obtenir plus d'informations sur l'optimisation de votre fonction Lambda, vous pouvez en savoir plus sur les démarrages à froid, les démarrages à chaud et la simultanéité du provisionnement dans le manuel guide du développeur AWS Lambda, ou consulter la série de blogs « Operating Lambda : optimisation des performances » de James Beswick, partie 1, partie 2, et partie 3.

Découpage et prêt à être exécuté pour les versions .NET antérieures à .NET 7

Si vous avez choisi d'utiliser des environnements d'exécution personnalisés Lambda pour une version de .NET antérieure à .NET 7, vous pouvez utiliser certaines fonctionnalités .NET pour réduire les temps de démarrage à froid.

PublishTrimmed réduira la taille globale du package que vous déployez en supprimant les bibliothèques inutiles du package.

PublishReadyToRun compilera votre code à l'avance, réduisant ainsi la quantité de compilation juste à temps requise. Mais cela augmente la taille du package que vous déployez.

Pour des performances optimales, vous devrez tester votre fonction lors de l'utilisation de ces options.

PublishTrimmed et PublishReadyToRun peuvent être activés à partir de votre fichier .csproj.

<PublishTrimmed>true</PublishTrimmed>
<PublishReadyToRun>true</PublishReadyToRun>

Conclusion

Ce module vous a présenté la création, le déploiement et l'appel de fonctions Lambda .NET. Il vous a donné un aperçu des différentes manières d'exécuter .NET sur AWS Lambda et a abordé certaines des raisons pour lesquelles vous pourriez choisir une méthode ou une autre. Il a également expliqué les concepts relatifs au « démarrage à froid » et aux optimisations.


Compilation native à l'avance pour .NET 7

NET 7, publié en novembre 2022, prend en charge la compilation native à l'avance (AOT). Les outils de modèles .NET pour AWS Lambda vous permettent de créer et de déployer des fonctions d'exécution personnalisées .NET 7. Lors des tests, les fonctions Lambda de .NET 7 ont enregistré des démarrages à froid jusqu'à 86 % plus rapides que les environnements d'exécution gérés par .NET 6.
 
Pour tirer parti de cette nouvelle fonctionnalité, vous devez mettre à jour vos modèles de projet Lambda .NET vers la version 6.7.0 ou ultérieure, et les extensions AWS pour .NET vers la version 5.6.1 ou ultérieure.
 
Pour effectuer les mises à jour, exécutez :
dotnet new -i "Amazon.Lambda.Templates::*"dotnet tool update -g Amazon.Lambda.Tools
Au moment de la rédaction de cet article, il existe deux modèles pour les fonctions Lambda AOT : lambda.NativeAOT et serverless.NativeAOT. Vous devrez également installer et exécuter Docker.

Évaluation des connaissances préalables

Vous avez maintenant terminé le module 2, Outils pour le développement .NET avec AWS Lambda. Le test suivant vous permettra de vérifier ce que vous avez appris jusqu'à présent.

1. Quelles sont les versions des environnements d'exécution gérés .NET proposées par le service Lambda ? (choisissez-en deux)

a. .NET Core 5

b. .NET 6

c. .NET 7

d. .NET Core 3.1

e. .NET Framework 4.8

2. À quoi fait référence le démarrage à froid ? (sélectionnez une option)

a. Le temps nécessaire pour démarrer un environnement d'exécution Lambda et le code d'initialisation de la fonction.

b. Fonction Lambda qui utilise le stockage AWS S3 Glacier.

c. Le temps nécessaire pour déployer votre code sur le service Lambda.

d. Le temps nécessaire à la mise à jour d'une fonction

3. Comment utilisez-vous le kit SDK AWS .NET avec vos fonctions .NET Lambda ?

a. Ajoutez une référence au package SDK dans votre fichier de projet.

b. Vous n'en avez pas besoin, les modèles de fonctions Lambda sont inclus

c. Vous n'en avez pas besoin, la boîte à outils pour les IDE l'inclut

d. Ajoutez le SDK au service Lambda via la console AWS

4. Lorsque vous créez un nouveau projet Lambda.EmptyFunction, quel est le nom du fichier qui spécifie la configuration de la fonction ?

a. serverless.template

b. lambda.csproj

c. aws-lambda-tools-defaults.json

5. Parmi les méthodes suivantes, lesquelles permettent d'invoquer une fonction Lambda ?

a. Ligne de commande utilisant l'outil Dotnet Lambda

b. Requêtes HTTPS

c. Appels depuis d'autres services AWS

d. Tout ce qui précède

Réponses : 1-bd, 2-a, 3-a, 4-c, 5-d

Conclusion

Ce module vous a présenté la création, le déploiement et l'appel de fonctions Lambda .NET. Il vous a donné un aperçu des différentes manières d'exécuter .NET sur AWS Lambda et a abordé certaines des raisons pour lesquelles vous pourriez choisir une méthode ou une autre. Il a également expliqué les concepts relatifs au « démarrage à froid » et aux optimisations.

Cette page vous a-t-elle été utile ?

COLLABORATION AVEC D'AUTRES SERVICES AWS