Progettazione di applicazioni Lambda
Un'applicazione basata sugli eventi ben progettata utilizza una combinazione di servizi AWS e codice personalizzato per elaborare e gestire richieste e dati. Questo capitolo si concentra su argomenti specifici di Lambda nella progettazione di applicazioni. Ci sono numerose considerazioni importanti per gli architetti serverless quando progettano applicazioni per sistemi di produzione affollati.
Molte delle best practice che si applicano allo sviluppo di software e ai sistemi distribuiti si applicano anche allo sviluppo di applicazioni serverless. L'obiettivo generale è sviluppare carichi di lavoro che siano:
-
Affidabili: offrendo agli utenti finali un elevato livello di disponibilità, i servizi serverless AWS sono affidabili perché progettati anche per evitare guasti.
-
Durevoli: offrendo opzioni di archiviazione che soddisfano le esigenze di durabilità del carico di lavoro.
-
Sicuri: seguendo le best practice e utilizzando gli strumenti forniti per proteggere l'accesso ai carichi di lavoro e limitare il raggio di esplosione.
-
Performanti: utilizzando le risorse di elaborazione in modo efficiente e soddisfando le esigenze di prestazioni degli utenti finali.
-
Efficienti in termini di costi: progettando architetture che evitino costi inutili, scalabili senza spese eccessive e che possano essere disattivate senza costi generali significativi.
I seguenti principi di progettazione possono aiutarti a creare carichi di lavoro che soddisfino questi obiettivi. Non tutti i principi possono essere applicati a tutte le architetture, ma dovrebbero guidarti nelle decisioni generali sull'architettura.
Utilizzare i servizi anziché il codice personalizzato
Le applicazioni serverless di solito comprendono diversi servizi AWS, integrati con codice personalizzato eseguito nelle funzioni Lambda. Sebbene Lambda possa essere integrato con la maggior parte dei servizi AWS, i servizi più comunemente utilizzati nelle applicazioni serverless sono:
| Categoria | AWSServizio |
|---|---|
|
Calcolo |
AWS Lambda |
|
Archiviazione dei dati |
Amazon S3 Amazon DynamoDB Amazon RDS |
|
API |
Amazon API Gateway |
|
Integrazione di applicazioni |
Amazon EventBridge Amazon SNS Amazon SQS |
|
Orchestrazione |
AWS Step Functions |
|
Streaming di dati e analisi |
Amazon Data Firehose |
Nota
Molti servizi serverless forniscono replica e supporto per più regioni, tra cui DynamoDB e Amazon S3. Le funzioni Lambda possono essere implementate in più regioni come parte di una pipeline di implementazione e API Gateway può essere configurato per supportare questa configurazione. Guarda questo esempio di architettura
Esistono molti modelli comuni e consolidati nelle architetture distribuite che è possibile creare autonomamente o implementare utilizzando i servizi AWS. Per la maggior parte dei clienti, investire tempo per sviluppare questi modelli partendo da zero ha poco valore commerciale. Quando l'applicazione richiede uno di questi modelli, utilizza il servizio AWS corrispondente:
| Pattern | AWSServizio |
|---|---|
|
Queue |
Amazon SQS |
|
Router di eventi |
Amazon EventBridge |
|
Pubblicazione/sottoscrizione (fan-out) |
Amazon SNS |
|
Orchestrazione |
AWS Step Functions |
|
API |
Amazon API Gateway |
|
Flussi di eventi |
Amazon Kinesis |
Questi servizi sono progettati per integrarsi con Lambda e puoi utilizzare l'infrastructure as code (IaC) per creare ed eliminare risorse nei servizi. Puoi utilizzare uno qualsiasi di questi servizi tramite l'SDK AWS
Informazioni sui livelli di astrazione Lambda
Il servizio Lambda limita l'accesso ai sistemi operativi, agli hypervisor e all'hardware sottostanti che eseguono le funzioni Lambda. Il servizio migliora e modifica continuamente l'infrastruttura per aggiungere funzionalità, ridurre i costi e rendere il servizio più performante. Il codice non deve presupporre alcuna conoscenza dell'architettura di Lambda né presupporre alcuna affinità hardware.
Allo stesso modo, le integrazioni di Lambda con altri servizi sono gestite da AWS con solo un numero limitato di opzioni di configurazione esposte. Ad esempio, quando API Gateway e Lambda interagiscono, non sussiste il concetto di bilanciamento del carico poiché è interamente gestito dai servizi. Inoltre, non hai alcun controllo diretto sulle zone di disponibilità
Questa astrazione ti aiuta a concentrarti sugli aspetti di integrazione dell'applicazione, sul flusso di dati e sulla logica aziendale in cui il carico di lavoro fornisce valore agli utenti finali. Consentire ai servizi di gestire i meccanismi sottostanti consente di sviluppare applicazioni più rapidamente con meno codice personalizzato da gestire.
Implementazione stateless nelle funzioni
Quando si creano funzioni Lambda, è necessario presupporre che l'ambiente esista solo per una singola invocazione. La funzione dovrebbe inizializzare qualsiasi stato richiesto al primo avvio. Ad esempio, la funzione potrebbe richiedere il recupero di dati da una tabella DynamoDB. Deve eseguire eventuali modifiche permanenti ai dati in un archivio durevole come Amazon S3, DynamoDB o Amazon SQS prima dell’uscita. Non dovrebbe basarsi su strutture di dati o file temporanei esistenti o su qualsiasi stato interno che verrebbe gestito da più invocazioni.
Per inizializzare le connessioni e le librerie del database o lo stato di caricamento, è possibile sfruttare l'inizializzazione statica. Poiché gli ambienti di esecuzione vengono riutilizzati ove possibile per migliorare le prestazioni, è possibile ammortizzare il tempo impiegato per inizializzare queste risorse su più invocazioni. Tuttavia, non è necessario archiviare alcuna variabile o dato utilizzato nella funzione all'interno di questo ambito globale.
Riduzione dell'associazione
La maggior parte delle architetture dovrebbe preferire molte funzioni più brevi rispetto a un numero inferiore di funzioni più grandi. Lo scopo di ogni funzione dovrebbe essere quello di gestire l'evento trasmesso alla funzione, senza alcuna conoscenza o aspettativa del flusso di lavoro complessivo o del volume delle transazioni. Ciò rende la funzione indipendente dall'origine eventi con un abbinamento minimo ad altri servizi.
Tutte le costanti di ambito globale che cambiano di rado devono essere implementate come variabili di ambiente per consentire aggiornamenti senza implementazioni. Eventuali informazioni segrete o sensibili devono essere archiviate in AWS Systems Manager Parameter Store o AWS Secrets Manager
Creazione di dati on demand anziché in batch
Molti sistemi tradizionali sono progettati per funzionare periodicamente ed elaborare batch di transazioni accumulati nel tempo. Ad esempio, un'applicazione bancaria può essere eseguita ogni ora per elaborare le transazioni dei bancomat in log centrali. Nelle applicazioni basate su Lambda, l'elaborazione personalizzata deve essere attivata da ogni evento, consentendo al servizio di aumentare la simultaneità secondo necessità, per fornire un'elaborazione delle transazioni quasi in tempo reale.
Sebbene sia possibile eseguire attività cron
Ad esempio, non è consigliabile utilizzare un processo batch che attiva una funzione Lambda per recuperare un elenco di nuovi oggetti Amazon S3. Questo perché il servizio può ricevere più nuovi oggetti tra un batch e l'altro di quanti ne possano essere elaborati in una funzione Lambda di 15 minuti.
Invece, Amazon S3 deve invocare la funzione Lambda ogni volta che un nuovo oggetto viene inserito nel bucket. Questo approccio è significativamente più scalabile e funziona quasi in tempo reale.
AWS Step Functions da tenere in considerazione per l’orchestrazione
I flussi di lavoro che coinvolgono la logica di ramificazione, diversi tipi di modelli di errore e la logica dei tentativi in genere utilizzano un orchestratore per tenere traccia dello stato dell'esecuzione complessiva. Evita di utilizzare le funzioni Lambda per questo scopo, poiché si ottengono routing per la gestione del codice ad accoppiamento stretto e complessi.
Con AWS Step Functions
È normale che i flussi di lavoro più semplici nelle funzioni Lambda diventino più complessi nel tempo. Quando si utilizza un'applicazione serverless di produzione, è importante identificare quando ciò accade, in modo da poter migrare questa logica su una macchina a stati.
Implementa l'idempotenza
I servizi serverless AWS, tra cui Lambda, sono tolleranti agli errori e progettati per gestirli. Ad esemoio, se un servizio richiama una funzione Lambda e si verifica un'interruzione del servizio, Lambda invoca la funzione in una zona di disponibilità diversa. Se la funzione emette un errore, Lambda ritenta l’invocazione.
Poiché lo stesso evento può essere ricevuto più di una volta, le funzioni devono essere progettate in modo da essere idempotenti
Puoi implementare l'idempotenza nelle funzioni Lambda utilizzando una tabella DynamoDB per tenere traccia degli identificatori elaborati di recente per determinare se la transazione è già stata gestita in precedenza. La tabella DynamoDB di solito implementa un valore Time To Live (TTL) per gli elementi con scadenza per limitare lo spazio di archiviazione utilizzato.
Utilizzo di più account AWS per la gestione delle quote
Molte Service Quotas in AWS sono impostate a livello di account. Ciò significa che man mano che aggiungi più carichi di lavoro, puoi esaurire rapidamente i tuoi limiti.
Un modo efficace per risolvere questo problema consiste nell'utilizzare più account AWS, dedicando ogni carico di lavoro al suo account specifico. Ciò impedisce che le quote vengano condivise con altri carichi di lavoro o risorse non di produzione.
In aggiunta, utilizzando Organizzazioni AWS
Un approccio comune consiste nel fornire a ogni sviluppatore un account AWS e quindi utilizzare account separati per la fase di distribuzione e produzione della versione beta:
In questo modello, ogni sviluppatore ha i propri limiti per l'account, quindi il loro utilizzo non ha alcun impatto sull'ambiente di produzione. Questo approccio consente inoltre agli sviluppatori di testare le funzioni Lambda localmente sulle proprie macchine di sviluppo con risorse cloud attive nei propri account individuali.