Carichi di lavoro .NET su AWS Lambda

MODULO 3

Modulo 3: .NET su AWS Lambda

 MODULO DI APPRENDIMENTO

Tieni presente che puoi seguire gli esempi presentati qui, ma non è obbligatorio.

AWS Lambda supporta più versioni .NET, su entrambe le architetture x86_64 e Arm64 (Graviton2) e puoi scegliere l'architettura che desideri. Il codice e il processo di distribuzione non cambiano.

Poiché Lambda è un servizio serverless, i costi sono calcolati solo in base all'uso effettivo. Se la tua funzione Lambda deve essere eseguita alcune volte al giorno, questo è tutto ciò che paghi. Ma questo è anche grazie al fatto che può dimensionarsi in base alle tue esigenze e può avviare anche migliaia di istanze contemporaneamente!

 Tempo richiesto per il completamento

60 minuti 

Prezzi

Come accennato in precedenza, paghi solo ciò che usi. L'importo da pagare viene calcolato in base al tempo di esecuzione della funzione Lambda (arrotondato al millisecondo più vicino) e alla quantità di memoria allocata alla funzione.

Tieni presente che nel calcolo del prezzo viene utilizzata la quantità di memoria allocata, non la quantità utilizzata durante un'invocazione. Ciò rende utile testare le funzioni per valutare la quantità massima di memoria utilizzata durante un'invocazione. Mantenere la memoria allocata alla quantità minima necessaria contribuirà a ridurre il costo dell'utilizzo delle funzioni Lambda. Consulta la pagina Prezzi di AWS Lambda per ulteriori informazioni.

Tieni presente che se la tua funzione Lambda utilizza altri servizi come S3 e Kinesis, potresti dover sostenere dei costi anche per questi servizi.

Versioni supportate di .NET

Esistono diversi modi per eseguire file binari .NET sulla piattaforma Lambda. Il più comune, e quello da considerare per primo, è l'uso di un runtime gestito fornito da AWS. È il modo più semplice per iniziare, il più conveniente e offre le migliori prestazioni. Se non vuoi o non puoi usare il runtime gestito, hai altre due scelte: un runtime personalizzato o un'immagine di container. Entrambe le opzioni hanno i loro vantaggi e svantaggi e verranno discusse più dettagliatamente di seguito.

Runtime gestiti

Il servizio AWS Lambda offre una serie di runtime popolari su cui eseguire il codice. In relazione ai runtime .NET, AWS mantiene il runtime aggiornato e dotato delle patch necessarie in base alle ultime versioni disponibili da Microsoft. Come sviluppatore non devi fare nulla in merito alla gestione del runtime che utilizzerà il tuo codice, se non specificare la versione che desideri utilizzare nel tuo file .csproj.

Al momento, AWS offre runtime gestiti solo per le versioni LTS (Long Term Support) di runtime .NET, ossia .NET 3.1 e .NET 6. I runtime gestiti .NET sono disponibili per entrambe le architetture x86_64 e arm64 e vengono eseguiti su Amazon Linux 2. Se desideri utilizzare una versione di .NET diversa da quelle offerte da AWS, puoi creare il tuo runtime personalizzato o un'immagine di container adatta alle tue esigenze.

Se sei interessato a uscire dal contesto .NET, è bene sapere che il servizio Lambda offre runtime gestiti anche per altri linguaggi: Node.js, Python, Ruby, Java e Go. Per i dettagli completi sull'elenco dei runtime gestiti e sulle versioni dei linguaggi supportati, consulta questa pagina sui runtime disponibili.

Runtime personalizzati

I runtime personalizzati sono runtime creati e raggruppati dall'utente. Ci sono diversi motivi per scegliere questa opzione. Il più comune è che si desidera utilizzare una versione .NET che non è offerta come runtime gestito dal servizio Lambda. Un altro motivo, meno comune, è quello di avere un controllo preciso sulle versioni secondarie e sulle patch del runtime.

La creazione di un runtime personalizzato richiede pochissimo sforzo da parte tua. Tutto quello che devi fare è passare:

--self-contained true al comando di compilazione.

Questo può essere fatto direttamente con dotnet build. Puoi farlo anche tramite il file aws-lambda-tools-defaults.json con il seguente parametro:

"msbuild-parameters": "--self-contained true"

Questo è tutto, un semplice flag del compilatore quando si raggruppa la funzione Lambda .NET. Il pacchetto da distribuire ora conterrà il tuo codice e i file richiesti dal runtime .NET che hai scelto.

Ora spetta a te applicare le patch e aggiornare il runtime come ritieni opportuno. L'aggiornamento del runtime richiede la ridistribuzione della funzione, poiché il codice della funzione e il runtime sono impacchettati insieme.

Il pacchetto distribuito è notevolmente più grande rispetto al runtime gestito perché contiene tutti i file di runtime necessari. Ciò influisce negativamente sui tempi di avvio a freddo (ne parleremo più avanti). Per ridurre queste dimensioni, prendi in considerazione l'utilizzo delle funzionalità di compilazione .NET Trimming e ReadyToRun. Ti consigliamo di leggere la documentazione su queste funzionalità prima di utilizzarle.

È possibile creare un runtime personalizzato con qualsiasi versione .NET eseguita su Linux. Un caso d'uso comune consiste nel distribuire funzioni con le versioni "correnti" o di anteprima di .NET.

Quando si utilizzano runtime personalizzati, è possibile avvalersi di un'ampia varietà di linguaggi offerti dalla community. Oppure si può costruire il proprio runtime personalizzato, come hanno fatto altri per eseguire linguaggi come Erlang e COBOL.

Immagini di container

Oltre al runtime gestito e a quello personalizzato, il servizio AWS Lambda offre anche la possibilità di impacchettare il codice in un'immagine di container e distribuirla al servizio Lambda. L'opzione è adatta ai team che hanno investito tempo nella creazione e distribuzione del proprio codice nei container o a coloro che necessitano di un maggiore controllo sul sistema operativo e sull'ambiente in cui viene eseguito il codice. Sono supportate immagini di dimensioni fino a 10 GB.

AWS fornisce una varietà di immagini di base per .NET e .NET Core. Queste immagini ti consentiranno di iniziare a lavorare molto rapidamente: https://gallery.ecr.aws/lambda/dotnet.

Un'altra opzione è creare un'immagine personalizzata specifica per la tua funzione. Questo è un caso d'uso più avanzato e richiede la modifica del Dockerfile in base alle proprie esigenze. Questo approccio non verrà trattato in questo corso, ma se segui questa strada, dai un'occhiata ai Dockerfile presenti in questo repository: https://github.com/aws/aws-lambda-dotnet/tree/master/LambdaRuntimeDockerfiles/Images.

Tieni presente che l'aggiornamento della funzione Lambda sarà più lento con i container a causa delle dimensioni di caricamento. I container hanno anche il più lento avvio a freddo delle tre opzioni. Maggiori informazioni su questo argomento più avanti nel modulo.

Scegli il runtime che fa per te

Se desideri le migliori prestazioni all'avvio, facilità di distribuzione, facilità di avvio e preferisci continuare a utilizzare le versioni LTS di .NET, scegli i runtime .NET gestiti.

Le immagini dei container sono un'ottima opzione che consente di utilizzare le immagini create da AWS per una varietà di versioni .NET. Oppure puoi scegliere la tua immagine di container e modificare il sistema operativo e l'ambiente in cui viene eseguito il codice. Le immagini dei container sono adatte anche per le organizzazioni che utilizzano già ampiamente i container.

Se hai requisiti molto specifici per quanto riguarda le versioni di .NET e le relative librerie di runtime e desideri controllarle tu stesso, prendi in considerazione l'utilizzo di un runtime personalizzato. Tuttavia, tieni presente che la manutenzione del runtime e l'applicazione di patch sono a carico tuo. Se Microsoft rilascia un aggiornamento di sicurezza, devi esserne a conoscenza e aggiornare il runtime personalizzato in modo appropriato. Dal punto di vista delle prestazioni, il runtime personalizzato ha l'avvio più lento delle tre opzioni.

Una volta avviata la funzione Lambda, le prestazioni del runtime gestito, dell'immagine del container e del runtime personalizzato saranno molto simili.

AWS SDK per .NET

Se hai sviluppato applicazioni .NET che utilizzano i servizi AWS, probabilmente hai utilizzato l'AWS SDK per .NET. L'SDK consente agli sviluppatori .NET di chiamare facilmente i servizi AWS in modo coerente e familiare. L'SDK viene aggiornato mano a mano che i servizi vengono rilasciati o aggiornati. L'SDK è disponibile per il download da NuGet.

Come accade per molte soluzioni relative ad AWS, l'SDK è suddiviso in pacchetti più piccoli, ognuno dei quali si occupa di un singolo servizio.

Ad esempio, se desideri accedere ai bucket S3 dalla tua applicazione .NET, utilizzerai il pacchetto NuGet AWSSDK.S3. Oppure, se desideri accedere a DynamoDB dalla tua applicazione .NET, dovresti utilizzare il pacchetto NuGet AWSSDK.DynamoDBv2.

E aggiungi solo i pacchetti NuGet di cui hai bisogno. Suddividendo l'SDK in pacchetti più piccoli, riduci le dimensioni del tuo pacchetto di implementazione.

Se il gestore della funzione Lambda deve ricevere eventi da altri servizi AWS, cerca i pacchetti NuGet specifici per gli eventi. Contengono i tipi pertinenti per gestire gli eventi. I pacchetti seguono il modello di denominazione di AWSSDK.Lambda.[SERVICE]Events.

Ad esempio, se la tua funzione Lambda viene attivata da:

eventi S3 in arrivo, usa il pacchetto AWSSDK.Lambda.S3Events

eventi Kinesis in arrivo, usa il pacchetto AWSSDK.Lambda.KinesisEvents

notifiche SNS in arrivo, usa il pacchetto AWSSDK.Lambda.SNSEvents

messaggi SQS in arrivo, usa il pacchetto AWSSDK.Lambda.SQSEvents

Usare l'SDK per interagire con i servizi AWS è molto semplice. Aggiungi un riferimento al pacchetto NuGet nel tuo progetto e poi chiama il servizio come faresti con qualsiasi altra libreria .NET che potresti usare.

Il fatto che tu stia utilizzando l'SDK da una funzione Lambda non ha alcun impatto sul modo in cui lo usi.

Tieni presente che non devi necessariamente aggiungere alcun pacchetto NuGet dell'AWS SDK al tuo progetto. Ad esempio, se la funzione Lambda chiama un server SQL AWS RDS, puoi semplicemente utilizzare Entity Framework per accedere al database. Non sono necessarie librerie aggiuntive specifiche di AWS. Ma se desideri recuperare un nome utente/password per il database da Secrets Manager, dovrai aggiungere il pacchetto NuGet AWSSDK.SecretsManager.

Una nota sulle autorizzazioni

Come regola generale, è consigliabile utilizzare il livello minimo di autorizzazioni necessario per eseguire un'attività. Durante questo corso, sarai incoraggiato a farlo e ti verrà mostrato come farlo.

Tuttavia, per semplicità didattica di questo corso, ti consigliamo di utilizzare un utente AWS con la policy AdministratorAccess allegata. Questa policy consente di creare i ruoli necessari per la distribuzione delle funzioni Lambda. Quando non lavori nell'ambito del corso, dovresti rimuovere questa policy dall'utente AWS.

Una funzione Lambda .NET in stile Hello World

Come hai visto in un modulo precedente, è molto semplice creare, distribuire e richiamare una funzione Lambda .NET. In questa sezione farai la stessa cosa, ma più lentamente, e spiegherò cosa sta succedendo in ogni passaggio. Parleremo anche del codice generato e dei file di configurazione.

Creare la funzione

È necessario installare gli strumenti richiesti per proseguire; consulta il modulo 3 per maggiori dettagli su come eseguire questa operazione.

Se non vuoi approfondirlo adesso, ecco un breve promemoria.

Installa i modelli di funzione Lambda .NET:

dotnet new -i Amazon.Lambda.Templates

Installa gli strumenti .NET per distribuire e gestire le funzioni Lambda:

dotnet tool install -g Amazon.Lambda.Tools

Ora che hai installato i modelli, puoi creare una nuova funzione

Dalla linea di comando esegui:

dotnet new lambda.EmptyFunction -n HelloEmptyFunction

In questo modo verrà creata una nuova directory chiamata HelloEmptyFunction. Al suo interno ci sono altre due directory: src e test. Come suggeriscono i nomi, la directory src contiene il codice per la funzione, mentre la directory test contiene i test di unità per la funzione. Navigando in queste directory, scoprirai che ognuna contiene un'altra directory al suo interno. All'interno di queste sottodirectory ci sono i file di codice per la funzione e i file di test di unità.

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

Diamo prima un'occhiata al file 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();
    }
}

Alcune note sulle righe che necessitano di una piccola spiegazione:

La riga 4 consente la conversione dell'input JSON in una classe .NET.

La riga 17 specifica che l'input JSON della funzione verrà convertito in una stringa.

La riga 17 specifica che un oggetto ILambdaContext viene passato come parametro, che può essere utilizzato per la registrazione, nonché per determinare il nome della funzione, da quanto tempo la funzione è in esecuzione e altre informazioni.

Come puoi vedere, il codice è molto semplice e dovrebbe essere familiare a chiunque abbia lavorato con C#.

Sebbene il metodo FunctionHandler in questo caso sia sincrono, le funzioni Lambda possono essere asincrone proprio come qualsiasi altro metodo .NET. Tutto quello che devi fare è cambiare FunctionHandler in

public async Task<string> FunctionHandler(..)

Diamo un'occhiata al file 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 riga 10 specifica che la funzione deve essere creata nella configurazione della versione.

La riga 11 specifica al servizio Lambda quale runtime utilizzare.

La riga 12 specifica la quantità di memoria da allocare alla funzione, in questo caso 256 MB.

La riga 13 specifica il timeout per la funzione, in questo caso 30 secondi. Il timeout massimo consentito è di 15 minuti.

La riga 14 specifica il gestore della funzione. Questo è il metodo che verrà richiamato dal servizio Lambda quando viene chiamata questa funzione.

Il gestore della funzione è composto da tre parti:

"AssemblyName::Namespace.ClassName::MethodName"

Un po' più tardi, creerai e distribuirai questa funzione al servizio AWS Lambda utilizzando la configurazione contenuta in questo file.

Ma prima diamo un'occhiata al progetto di test e al suo file 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);
    }
}

Il codice qui è relativamente semplice e utilizza il framework di test xUnit. Puoi testare le tue funzioni Lambda proprio come faresti con qualsiasi altro metodo.

La riga 14 crea una nuova istanza della classe Function.

La riga 15 crea una nuova istanza della classe TestLambdaContext, che verrà passata alla funzione Lambda nella riga successiva.

La riga 16 richiama il metodo FunctionHandler sulla funzione, passando la stringa "hello world" e il contesto. Memorizza la risposta nella variabile upperCase.

La riga 18 afferma che la variabile upperCase è uguale a "HELLO WORLD".

Puoi eseguire questo test dalla linea di comando o all'interno del tuo IDE preferito. Esistono altri tipi di test che possono essere eseguiti sulle funzioni Lambda. Se sei interessato a saperne di più, consulta un modulo successivo in cui scoprirai una varietà di modi per testare ed eseguire il debug delle funzioni Lambda.

Distribuzione della funzione

Ora che disponi di una funzione Lambda e potresti aver eseguito un test di unità, è il momento di distribuire la funzione Lambda nel servizio AWS Lambda.

Dalla linea di comando, accedi alla directory contenente il file HelloEmptyFunction.csproj ed esegui il comando seguente:

dotnet lambda deploy-function HelloEmptyFunction  

Vedrai un output che include quanto segue (l'ho tagliato per chiarezza):

... 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 riga 1 compila e pubblica il progetto. Tieni presente che il runtime è linux-x64 e il flag autonomo è false (il che significa che la funzione utilizzerà il runtime .NET gestito sul servizio Lambda, anziché un runtime personalizzato).

La riga 2 comprime il progetto pubblicato in un file zip.

Le righe 3-8 mostrano i file che vengono compressi.

La riga 9 conferma che il file zip è stato creato.

Successivamente ti verrà chiesto "Select IAM Role that to provide AWS credentials to your code:" (Seleziona il ruolo IAM per fornire le credenziali AWS al tuo codice), ti potrebbe essere presentato un elenco di ruoli che hai creato in precedenza, ma in fondo all'elenco ci sarà l'opzione "*** Create new IAM Role ***" (Crea un nuovo ruolo IAM); digita quel numero accanto all'opzione.

Ti verrà chiesto "Enter name of the new IAM Role:"(Inserisci il nome del nuovo ruolo IAM). Digita "HelloEmptyFunctionRole".

Ti verrà quindi chiesto "Select IAM Policy to attach to the new role and grant permissions" (Seleziona la policy IAM da allegare al nuovo ruolo e concedi le autorizzazioni) e verrà presentato un elenco di policy. Avrà un aspetto simile a quello riportato di seguito, ma il tuo potrebbe essere più lungo:

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 ...) 

Seleziona "AWSLambdaBasicExecutionRole", è la numero 6 sulla lista.

Dopo un momento, vedrai:

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

Ora puoi richiamare la funzione.

Richiamo della funzione

Linea di comando

Utilizza gli strumenti lambda dotnet per richiamare la funzione dalla shell (interprete di comandi) di tua scelta:

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

Per semplici funzioni Lambda come quelle precedenti, non esiste un JSON su cui fare l'escape, ma quando si desidera passare un JSON che deve essere deserializzato, l'escape del payload varierà a seconda della shell (interprete di comandi) che si sta utilizzando.

Verrà visualizzato un output simile al seguente:

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

L'output "Payload:" è la risposta della funzione Lambda.

Nota: la coda del log contiene informazioni utili sull'invocazione della funzione Lambda, ad esempio, per quanto tempo è stata eseguita e quanta memoria è stata utilizzata. Per una funzione semplice come questa, 244,83 ms potrebbero sembrare molti, ma questa è stata la prima volta che la funzione è stata richiamata, il che significa che è necessario eseguire più lavoro. Le invocazioni successive sarebbero state più rapide. Per ulteriori informazioni, consulta la sezione sugli avvii a freddo.

Facciamo una piccola modifica al codice per aggiungere alcune delle nostre istruzioni log.

Aggiungi quanto segue sopra l'istruzione return nel metodo FunctionHandler:

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

Implementa nuovamente utilizzando:

dotnet lambda deploy-function HelloEmptyFunction

Questa volta non ci saranno domande sul ruolo o sulle autorizzazioni.

Dopo che la funzione è stata implementata, puoi richiamarla nuovamente.

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

Questa volta, l'output conterrà un'istruzione di log aggiuntiva.

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

Qui, alla riga 6, troverai l'istruzione log. I log delle funzioni Lambda vengono scritti anche nei file di log CloudWatch (a condizione che tu abbia fornito le autorizzazioni alla funzione Lambda).

Console AWS

Un altro modo per richiamare la funzione è attraverso la console AWS.

Accedi alla console AWS e seleziona la funzione Lambda che desideri richiamare.

Fai clic sulla scheda Test.

Scorri verso il basso fino alla sezione JSON evento e inserisci "Richiama una funzione Lambda", incluse le virgolette.

Quindi fai clic sul pulsante Test.

L'output che vedrai sarà simile a questo.

Nota: sarà visibile anche l'output del log.

Una funzione Lambda .NET che accetta un payload JSON

L'esempio precedente era una semplice funzione che prendeva una stringa e restituiva una stringa, è un buon esempio per iniziare.

Ma probabilmente vorrai inviare payload JSON alle funzioni Lambda. Infatti, se un altro servizio AWS richiama la tua funzione Lambda, invierà un payload JSON. Questi payload JSON sono, di solito piuttosto complessi, ma un modello per il payload sarà disponibile su NuGet. Ad esempio, se stai gestendo eventi Kinesis con la tua funzione Lambda, il pacchetto Amazon.Lambda.KinesisEvents dispone di un modello KinesisEvent. Lo stesso vale per gli eventi S3, gli eventi SQS, ecc.

Invece di utilizzare uno di questi modelli ora, richiamerai una nuova funzione Lambda con un payload che rappresenta una persona.

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

La classe C# appropriata per deserializzare il payload JSON è:

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

Crea la funzione

Come in precedenza, crea una nuova funzione utilizzando il seguente comando:

dotnet new lambda.EmptyFunction -n HelloPersonFunction

Modifica la funzione

Accedi al file Function.cs in HelloPersonFunction/src/HelloPersonFunction.

Cambia il codice del metodo FunctionHandler in questo modo:
public string FunctionHandler(Person input, ILambdaContext context)
{
    return $"Hello, {input.FirstName} {input.LastName}";
}
Nella parte inferiore del file, aggiungi una nuova classe:
public class Person 
{
    public string FirstName { get; init; }
    public string LastName { get; init; }  
}

Questo è lo stesso comando che hai usato qualche minuto fa:

Questo è lo stesso comando che hai usato qualche minuto fa:
dotnet lambda deploy-function HelloPersonFunction

Richiama la funzione

Linea di comando
 

Ora la tua funzione Lambda può accettare un payload JSON. Tuttavia, il modo in cui lo richiami dipende dalla shell (interprete di comandi) che stai usando a causa del modo in cui viene eseguito l'escape del JSON in ogni shell (interprete di comandi).

Se stai usando PowerShell o bash, usa:

dotnet lambda invoke-function HelloPersonFunction --payload '{ \"FirstName\": \"Alan\", \"LastName\": \"Adams\" }'
Se invece stai usando il prompt dei comandi di Windows, usa:
dotnet lambda invoke-function HelloPersonFunction --payload "{ \"FirstName\": \"Alan\", \"LastName\": \"Adams\" }"
Questo è un semplice esempio. Ma, ovviamente, il JSON può essere complesso quanto necessario.
Console AWS
 
Un altro modo per richiamare la funzione è attraverso la console AWS.

Accedi alla console AWS e seleziona la funzione Lambda che desideri richiamare.
Fai clic sulla scheda Test.
Scorri verso il basso fino alla sezione JSON evento e inserisci:
{
  "FirstName": "Alan",
  "LastName": "Adams"
}
Quindi fai clic sul pulsante Test.

L'output che vedrai sarà simile a questo.
Gli esempi precedenti sono stati abbastanza semplici e la funzione Lambda non ha utilizzato nessun altro servizio AWS. Si tratta comunque di un ottimo modo per iniziare e acquisire familiarità con il servizio AWS Lambda, scrivere funzioni Lambda, implementare pacchetti compilati e richiamare le funzioni.

Nella prossima sezione, vedrai come implementare una funzione Lambda che risponde alle richieste HTTP.

Creazione ed esecuzione di un'applicazione Web API come funzione Lambda

Negli esempi precedenti, le funzioni Lambda venivano tutte richiamate tramite la linea di comando o nella funzionalità di test del servizio Lambda nella console AWS.

È possibile però richiamare la funzione Lambda anche tramite una richiesta HTTP, un caso d'uso molto comune.

Gli strumenti AWS per .NET offrono alcuni modelli da utilizzare per la creazione di una semplice funzione Lambda che agisce da host per un'applicazione API Web.

Il più familiare sarà probabilmente il modello serverless.AspNetCoreWebAPI. Questo modello crea una semplice applicazione API Web che può essere richiamata tramite una richiesta HTTP. Il modello di progetto include un modello di configurazione CloudFormation che crea un Gateway API in grado di inoltrare le richieste HTTP alla funzione Lambda.

Quando viene implementato su AWS Lambda, il Gateway API traduce la richiesta HTTP in un evento Gateway API e invia il JSON alla funzione Lambda. Nessun server Kestrel è in esecuzione nella funzione Lambda quando viene implementata nel servizio Lambda.

Ma quando esegui il Kernel localmente, viene avviato un server web Kestrel, così da semplificare la scrittura e il test del codice come con qualsiasi applicazione API Web. Puoi anche eseguire il normale debug linea per linea. Non devi scendere a nessun compromesso!

Crea la funzione

Dalla linea di comando, esegui il comando seguente:
dotnet new serverless.AspNetCoreWebAPI -n HelloAspNetCoreWebAPI
Questo crea una nuova directory chiamata HelloAspNetCoreWebAPI. Al suo interno ci sono altre due directory, src e test. Come suggeriscono i nomi, la directory src contiene il codice per la funzione, mentre la directory test contiene i test di unità per la funzione. Navigando in queste directory, scoprirai che ognuna contiene un'altra directory al suo interno. All'interno di queste sottodirectory ci sono i file di codice per la funzione e i file di test di unità.
├───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

Implementa la funzione

L'implementazione di una funzione basata su un modello serverless.* è un po' più complicata rispetto all'implementazione di una funzione basata su un modello lambda.*.

Prima di tentare di implementare la funzione serverless, è necessario un bucket S3. Questo verrà utilizzato dagli strumenti di implementazione per archiviare uno stack CloudFormation.

Puoi usare un bucket S3 esistente o, se non ne hai uno, segui le istruzioni riportate di seguito.
Creazione di un bucket S3
 
Se stai usando la regione us-east-1, usa il seguente comando per creare il bucket:
aws s3api create-bucket --bucket your-unique-bucket-name1234 
O se utilizzi una regione diversa
aws s3api create-bucket --bucket your-unique-bucket-name1234 --create-bucket-configuration LocationConstraint=REGION
Ho creato un bucket in us-east-1, chiamato lambda-course-2022.
aws s3api create-bucket --bucket lambda-course-2022 
Torna all'implementazione della funzione
 
Ora che disponi di un bucket S3, puoi eseguire il comando di implementazione:
dotnet lambda deploy-serverless
Ti verrà richiesto di inserire un nome per lo stack CloudFormation.
Enter CloudFormation Stack Name: (CloudFormation stack name for an AWS Serverless application)
Digita AspNetCoreWebAPI

Ti verrà quindi chiesto il nome del bucket S3. Usa il nome del bucket che hai creato in precedenza o un bucket esistente che desideri utilizzare a questo scopo.

Dopo averlo inserito, inizia il processo di creazione e implementazione.

Ciò richiederà più tempo rispetto agli esempi che utilizzano i modelli di progetto lambda.* perché c'è più infrastruttura da creare e cablare.

L'output verrà suddiviso in due sezioni distinte.

La sezione superiore sarà simile a quella che hai visto durante l'implementazione delle funzioni in precedenza, una pubblicazione e uno zip del progetto, ma questa volta l'artefatto viene caricato su 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%
Successivamente, viene creato lo stack CloudFormation e vengono implementate tutte le risorse necessarie.
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/

In basso c'è l'URL pubblico che da usare per richiamare l'API.

Richiamo della funzione

Tentando di aprire quell'URL nel tuo browser, o Fiddler/Postman, ecc., vedrai una risposta del tipo "Benvenuto nell'esecuzione di ASP.NET Core su AWS Lambda".

Quindi prova ad aprire https://xxxxxxxx.execute-api.us-east-1.amazonaws.com/Prod/api/values. In questo modo richiamerai il metodo GET del controller dei valori, proprio come in una normale applicazione API Web.

Nota: quando si utilizza un Gateway API, il gateway impone il proprio timeout di 29 secondi. Se la funzione Lambda funziona più a lungo, non riceverai una risposta.

Se sei interessato, ci sono alcuni modi per esaminare le risorse che sono state create.

Per esaminare le risorse AWS create, puoi utilizzare:
aws cloudformation describe-stack-resources --stack-name AspNetCoreWebAPI
Questo ti fornirà dettagli su ogni risorsa dello stack.

Se vuoi un output più succinto, usa:
aws cloudformation describe-stack-resources --stack-name AspNetCoreWebAPI --query 'StackResources[].[{ResourceType:ResourceType, LogicalResourceId:LogicalResourceId, PhysicalResourceId:PhysicalResourceId}]'
Un altro modo è aprire la console AWS e accedere al servizio Lambda. Sulla sinistra dello schermo, seleziona Applicazione (anziché funzioni).


Vedrai l'applicazione che hai creato. Selezionala, quindi scorri fino alla fine della pagina che si apre. Vedrai tutte le risorse che sono state create qui.
Hai completato la visione degli esempi di funzioni Lambda, il primo era un semplice Hello World che richiedeva una stringa, il secondo era anch'esso molto semplice ma richiedeva un oggetto JSON e il terzo era un po' più complesso, ma comunque molto facile da creare e implementare.

Con questi esempi, puoi creare e implementare le tue funzioni Lambda. E, magari, potresti aver capito qualcosa su come vengono richiamate le funzioni Lambda .NET. Questo è l'argomento della prossima sezione.

Funzione URL: un'alternativa ai Gateway API

Se tutto ciò di cui hai bisogno è una funzione Lambda che risponda a una semplice richiesta HTTP, dovresti prendere in considerazione l'utilizzo degli URL della funzione Lambda.

Consentono di assegnare un endpoint HTTPS a una funzione Lambda. Dopodiché si richiama la funzione Lambda effettuando una richiesta all'endpoint HTTPS. Per ulteriori informazioni, consulta questo post del blog e questi documenti.

Eliminazione delle risorse create

Per eliminare le funzioni Lambda, esegui:
dotnet lambda delete-function HelloEmptyFunction  
dotnet lambda delete-function HelloPersonFunction

Nota: i comandi precedenti non eliminano il ruolo che hai creato.

Per eliminare la funzione Lambda che agisce da host per l'applicazione Web API e tutte le risorse associate, esegui:

dotnet lambda delete-serverless AspNetCoreWebAPI

Come viene richiamata una funzione Lambda .NET

Come puoi vedere dagli esempi precedenti, puoi richiamare una funzione Lambda .NET con una semplice stringa, un oggetto JSON e una richiesta HTTP. Le funzioni Lambda possono essere richiamate anche da altri servizi come S3 (quando si verifica una modifica al file), Kinesis (quando arriva un evento), DynamoDB (quando si verifica una modifica su una tabella), SMS (quando arriva un messaggio), Step Functions, ecc.

In che modo una funzione Lambda gestisce tutte queste modalità di richiamo diverse?

In pratica, queste funzioni Lambda vengono richiamate quando il servizio Lambda esegue il gestore di funzioni e gli passa l'input JSON. Se hai dato uno sguardo ad aws-lambda-tools-defaults.json, puoi vedere il "function-handler": specificato. Per le funzioni Lambda .NET, il gestore è composto da "AssemblyName::Namespace.ClassName::MethodName".

Le funzioni Lambda possono essere richiamate anche passando loro un flusso, questo rappresenta tuttavia uno scenario meno comune. Consulta la pagina sulla gestione dei flussi per ulteriori informazioni.

Ogni funzione Lambda ha un unico gestore.

Insieme all'input JSON, il gestore della funzione Lambda può anche accettare un oggetto ILambdaContext opzionale. Ciò consente di accedere alle informazioni sull'invocazione corrente, come il tempo rimasto per il completamento, il nome e la versione della funzione. Tramite l'oggetto ILambdaContext, è inoltre possibile scrivere messaggi log.

Tutti gli eventi sono in formato JSON

Ciò che rende molto semplice per un servizio AWS richiamare una funzione Lambda .NET è che questi servizi emettono JSON e, come discusso in precedenza, la funzione Lambda .NET accetta input JSON. Gli eventi generati da diversi servizi producono tutti JSON di forma diversa, ma i pacchetti NuGet degli eventi AWS Lambda includono tutti i tipi di oggetti pertinenti necessari per serializzare nuovamente il JSON in un oggetto su cui lavorare.

Vedi https://www.nuget.org/packages?packagetype=&sortby=relevance&q=Amazon.Lambda&prerel=True per un elenco dei pacchetti Lambda disponibili, dovrai cercare all'interno di questi risultati il tipo di evento che ti interessa.

Ad esempio, se desideri attivare una funzione Lambda in risposta a una modifica di file su un bucket S3, devi creare una funzione Lambda che accetti un oggetto di tipo S3Event. Quindi aggiungi il pacchetto Amazon.Lambda.S3Events al tuo progetto. Quindi cambia il metodo del gestore delle funzioni in:

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

Questo è tutto ciò di cui hai bisogno per gestire l'evento S3, puoi esaminare programmaticamente l'evento, vedere quale azione è stata eseguita sul file, in quale bucket si trovava, ecc. Amazon.Lambda.S3Events ti consente di lavorare con l'evento, non con S3 stesso, se desideri interagire con il servizio S3, devi aggiungere anche il pacchetto AWSSDK.S3 NuGet al tuo progetto. Un modulo successivo approfondirà l'argomento dei servizi AWS che richiamano le funzioni Lambda.

Lo stesso schema segue per altri tipi di eventi, aggiungi il pacchetto NuGet, modifica il parametro nel gestore della funzione e quindi puoi lavorare con l'oggetto evento.

Ecco alcuni dei pacchetti comuni che potresti usare per gestire gli eventi di altri servizi -

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

Non sei limitato all'utilizzo di tipi di eventi definiti da AWS quando richiami una funzione Lambda. Puoi creare tu stesso qualsiasi tipo di evento, ricorda che la funzione Lambda può accettare qualsiasi JSON che invii

Come avviene la serializzazione

Ricorderai che esistono due grandi categorie di modelli di progetto Lambda, quelle che iniziano con "lambda." e quelli che iniziano con "serverless.".

Nel caso dei modelli "lambda.", c'è un attributo assembly nella parte superiore del file Function.cs, che si occupa della deserializzazione dell'evento in entrata nel tipo .NET del gestore di funzioni. Nel file .csproj, c'è un riferimento al pacchetto Amazon.Lambda.Serialization.SystemTextJson.
[assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))]
Non devi fare nient'altro.

Per i modelli "serverless.", funziona in modo leggermente diverso.

Il gestore della funzione è specificato nel file serverless.template. Se stai implementando un'applicazione Serverless.AspNetCoreWebAPI, cerca il valore in Resources.AspNetCoreFunction.Properties.Handler. Il gestore per questo tipo di progetto terminerà nel modulo: Assembly::Namespace.LambdaEntryPoint::FunctionHandlerAsync.

La classe LambdaEntryPoint sarà nel tuo progetto ed eredita da una classe che ha un metodo FunctionHandlerAsync.

Il gestore di funzioni può essere impostato per gestire quattro diversi tipi di eventi: una REST API Gateway API, un payload API HTTP Gateway API versione 1.0, un payload API HTTP Gateway API versione 2.0 e un Application Load Balancer.

Modificando la classe da cui eredita LambdaEntryPoint, puoi cambiare il tipo di evento JSON gestito dal gestore della funzione.

Anche se sembra che la funzione Lambda stia rispondendo a una richiesta HTTP che la invii, con JSON che definisci, non è così. In realtà, la tua richiesta HTTP viene gestita da un gateway o da un sistema di bilanciamento del carico, che quindi crea un evento JSON che viene inviato al tuo gestore di funzioni. Questo evento JSON conterrà i dati originariamente inclusi nella richiesta HTTP, fino all'indirizzo IP di origine e alle intestazioni della richiesta.

Simultaneità

Quando si lavora con le funzioni Lambda è necessario considerare due tipi di simultaneità: riservata e fornita.

Un account AWS ha un limite massimo predefinito sul numero di esecuzioni Lambda simultanee. Al momento della stesura di questo documento, tale limite è 1.000.

Quando si specifica la simultaneità riservata per una funzione, si garantisce che la funzione sarà in grado di raggiungere il numero specificato di esecuzioni simultanee. Ad esempio, se la tua funzione ha una simultaneità riservata di 200, stai assicurando che la funzione sarà in grado di raggiungere 200 esecuzioni simultanee. Nota: rimangono 800 esecuzioni simultanee per altre funzioni (1000-200=800).

Quando si specifica la simultaneità fornita, si inizializza un numero specificato di ambienti di esecuzione Lambda. Una volta inizializzate, la funzione Lambda sarà in grado di rispondere immediatamente alle richieste, evitando il problema degli "avvii a freddo". Tuttavia, è prevista una commissione associata all'utilizzo della simultaneità fornita.

Per ulteriori informazioni, consulta gestione della simultaneità riservata Lambda e gestione della simultaneità fornita Lambda.

Avvii a freddo e avvii a caldo

Prima di poter richiamare la funzione Lambda, è necessario inizializzare un ambiente di esecuzione, che viene fatto per tuo conto dal servizio Lambda. Il codice sorgente viene scaricato da un bucket S3 gestito da AWS (per le funzioni che utilizzano runtime gestiti e runtime personalizzati) o da un Elastic Container Registry (per le funzioni che utilizzano immagini di container).

La prima volta che la funzione viene eseguita, il codice deve essere JITed e il codice di inizializzazione deve essere eseguito (ad esempio il costrutto). Ciò si aggiunge al tempo di avvio a freddo.

Se la tua funzione viene richiamata regolarmente, rimarrà "calda", ovvero l'ambiente di esecuzione verrà mantenuto. Le successive invocazioni della funzione non risentiranno del tempo di avvio a freddo. Gli "avvii a caldo" sono significativamente più veloci degli "avvii a freddo".

Se la funzione non viene richiamata per un certo periodo (l'ora esatta non è specificata dal servizio Lambda), l'ambiente di esecuzione viene rimosso. La successiva invocazione della funzione comporterà nuovamente un avvio a freddo.

Se si carica una nuova versione del codice della funzione, la successiva invocazione della funzione comporterà un avvio a freddo.

Le tre opzioni per eseguire .NET su Lambda, runtime gestito, runtime personalizzato e container ospitato hanno ciascuna profili di avvio a freddo diversi. Il più lento è il container, il successivo più lento è il runtime personalizzato e il più veloce è il runtime gestito. Se possibile, dovresti sempre optare per il runtime gestito quando esegui le funzioni Lambda .NET.

È stato riscontrato che gli avvii a freddo si verificano più spesso negli ambienti di test o sviluppo che negli ambienti di produzione. In un'analisi AWS, gli avvii a freddo si verificano in meno dell'1% delle invocazioni.

Se hai una funzione Lambda in produzione che viene utilizzata raramente, ma che deve rispondere rapidamente a una richiesta e vuoi evitare avvii a freddo, puoi utilizzare la simultaneità fornita o utilizzare un meccanismo per effettuare un "ping" frequente sulla tua funzione per mantenerla attiva.

Se sei interessato a maggiori informazioni sull'ottimizzazione della tua funzione Lambda, puoi leggere informazioni sugli avvii a freddo, sugli avvii a caldo e sulla simultaneità fornita nella Guida per gli sviluppatori AWS Lambda, o consulta la serie di blog a cura di James Beswick su Funzionalità Lambda: ottimizzazione delle prestazioni - parte 1, parte 2 e parte 3.

Trimming e Ready to Run per versioni .NET precedenti a .NET 7

Se hai scelto di utilizzare i runtime personalizzati Lambda per una versione di .NET precedente a .NET 7, ci sono un paio di funzionalità .NET che puoi utilizzare per ridurre i tempi di avvio a freddo.

PublishTrimmed ridurrà la dimensione complessiva del pacchetto distribuito eliminando le librerie non necessarie dal pacchetto.

PublishReadyToRun eseguirà una compilazione anticipata del codice, riducendo così la quantità di compilazione just-in-time richiesta. Ma aumenta le dimensioni del pacchetto che implementi.

Per prestazioni ottimali, dovrai testare la tua funzione quando utilizzi queste opzioni.

PublishTrimmed e PublishReadyToRun possono essere attivate dal tuo file .csproj.

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

Conclusioni

Questo modulo ti ha illustrato come creare, implementare e invocare le funzioni Lambda .NET. Ti ha fornito una panoramica dei vari modi in cui puoi eseguire .NET su AWS Lambda e ha spiegato alcuni dei motivi per cui potresti scegliere un modo o l'altro. Ha inoltre presentato i concetti relativi all'"avvio a freddo" e alle ottimizzazioni.


Compilazione nativa anticipata per .NET 7

NET 7, rilasciata a novembre 2022, supporta la compilazione nativa anticipata (AOT). Lo strumento modello .NET per AWS Lambda consente di creare e implementare funzioni di runtime personalizzate .NET 7. Nei test, le funzioni Lambda .NET 7 offrono avvio a freddo fino all'86% più veloci rispetto ai runtime gestiti NET 6.
 
Per sfruttare questa nuova funzionalità, devi aggiornare i modelli di progetto .NET Lambda alla versione 6.7.0 o successiva e le estensioni AWS per .NET alla versione 5.6.1 o successiva.
 
Per eseguire gli aggiornamenti esegui:
dotnet new -i "Amazon.Lambda.Templates::*"dotnet tool update -g Amazon.Lambda.Tools
Al momento della scrittura, esistono due modelli per le funzioni AOT Lambda: lambda.NativeAOT e serverless.NativeAOT. Dovrai anche installare ed eseguire Docker.

Verifica delle conoscenze

Hai completato il Modulo 2, Strumenti per lo sviluppo di .NET con AWS Lambda. Il seguente test ti consentirà di verificare ciò che hai imparato finora.

1. Quali versioni dei runtime gestiti .NET offre il servizio Lambda? (seleziona due risposte)

a. .NET Core 5

b. .NET 6

c. .NET 7

d. .NET Core 3.1

e. .NET Framework 4.8

2. Cosa si intende per avvio a freddo? (seleziona una risposta)

a. Il tempo necessario per avviare un ambiente di esecuzione Lambda e il codice di inizializzazione per la funzione.

b. Una funzione Lambda che utilizza l'archiviazione di AWS S3 Glacier.

c. Il tempo necessario per implementare il codice nel servizio Lambda.

d. Il tempo necessario per aggiornare una funzione

3. In che modo AWS SDK per .NET può essere utile con le funzioni Lambda .NET?

a. Aggiunge un riferimento al pacchetto SDK nel file di progetto.

b. Non è necessario, è incluso nei modelli di funzione Lambda

c. Non è necessario, in quanto già incluso nel kit di strumenti per gli ambienti di sviluppo integrato (IDE)

d. Aggiunge l'SDK al servizio Lambda tramite la console AWS

4. Quando crei un nuovo progetto lambda.EmptyFunction, qual è il nome del file che specifica la configurazione per la funzione?

a. serverless.template

b. lambda.csproj

c. aws-lambda-tools-defaults.json

5. Attraverso quali dei seguenti modi è possibile richiamare una funzione Lambda?

a. Linea di comando, utilizzando gli strumenti lambda dotnet

b. Richieste https

c. Chiamate da altri servizi AWS

d. Tutte le opzioni precedenti

Risposte: 1-bd, 2-a, 3-a, 4-c, 5-d

Conclusioni

Questo modulo ti ha introdotto alla creazione, implementazione e richiamo di funzioni Lambda .NET. Ti ha fornito una panoramica dei vari modi in cui puoi eseguire .NET su AWS Lambda e ha spiegato alcuni dei motivi per cui potresti scegliere un modo o l'altro. Ha inoltre spiegato i concetti relativi all'avvio a freddo e alle ottimizzazioni.

Questa pagina è stata utile?

LAVORARE CON ALTRI SERVIZI AWS