Implementa il modello di saga serverless utilizzando AWS Step Functions - Prontuario AWS

Le traduzioni sono generate tramite traduzione automatica. In caso di conflitto tra il contenuto di una traduzione e la versione originale in Inglese, quest'ultima prevarrà.

Implementa il modello di saga serverless utilizzando AWS Step Functions

Creato da Tabby Ward (AWS), Rohan Mehta (AWS) e Rimpy Tewani (AWS)

Ambiente: PoC o pilota

Tecnologie: modernizzazione; serverless; native per il cloud

Carico di lavoro: open source

Servizi AWS: Amazon API Gateway; Amazon DynamoDB; AWS Lambda; Amazon SNS; AWS Step Functions

Riepilogo

In un'architettura di microservizi, l'obiettivo principale è creare componenti disaccoppiati e indipendenti per promuovere agilità, flessibilità e tempi di commercializzazione più rapidi per le applicazioni. Come risultato del disaccoppiamento, ogni componente dei microservizi ha il proprio livello di persistenza dei dati. In un'architettura distribuita, le transazioni commerciali possono estendersi su più microservizi. Poiché questi microservizi non possono utilizzare una singola transazione ACID (atomicità, coerenza, isolamento, durabilità), è possibile che si ottengano transazioni parziali. In questo caso, è necessaria una certa logica di controllo per annullare le transazioni che sono già state elaborate. Il modello a saga distribuito viene in genere utilizzato per questo scopo. 

Il modello a saga è un modello di gestione degli errori che aiuta a stabilire la coerenza nelle applicazioni distribuite e coordina le transazioni tra più microservizi per mantenere la coerenza dei dati. Quando si utilizza il modello saga, ogni servizio che esegue una transazione pubblica un evento che attiva i servizi successivi per eseguire la transazione successiva nella catena. Questo continua fino al completamento dell'ultima transazione della catena. Se una transazione commerciale fallisce, saga orchestra una serie di transazioni di compensazione che annullano le modifiche apportate dalle transazioni precedenti.

Questo modello dimostra come automatizzare la configurazione e la distribuzione di un'applicazione di esempio (che gestisce le prenotazioni di viaggi) con tecnologie serverless come AWS Step Functions, AWS Lambda e Amazon DynamoDB. L'applicazione di esempio utilizza anche Amazon API Gateway e Amazon Simple Notification Service (Amazon SNS) per implementare un coordinatore dell'esecuzione di saga. Il pattern può essere distribuito con un framework Infrastructure as code (IaC) come AWS Cloud Development Kit (AWS CDK), AWS Serverless Application Model (AWS SAM) o Terraform.

Per ulteriori informazioni sul modello saga e altri modelli di persistenza dei dati, consulta la guida Enabling data persistence in microservices sul sito Web AWS Prescriptive Guidance.

Prerequisiti e limitazioni

Prerequisiti

  • Un account AWS attivo.

  • Autorizzazioni per creare uno CloudFormation stack AWS. Per ulteriori informazioni, consulta Controllare l'accesso nella CloudFormation documentazione.

  • Framework IaC di tua scelta (AWS CDK, AWS SAM o Terraform) configurato con il tuo account AWS in modo da poter utilizzare la CLI del framework per distribuire l'applicazione.

  • NodeJS, utilizzato per creare l'applicazione ed eseguirla localmente.

  • Un editor di codice a tua scelta (come Visual Studio Code, Sublime o Atom).

Versioni del prodotto

Limitazioni

L'event sourcing è un modo naturale per implementare il modello di orchestrazione della saga in un'architettura di microservizi in cui tutti i componenti sono liberamente accoppiati e non hanno una conoscenza diretta l'uno dell'altro. Se la transazione prevede un numero limitato di passaggi (da tre a cinque), il modello a saga potrebbe essere la soluzione ideale. Tuttavia, la complessità aumenta con il numero di microservizi e il numero di passaggi. 

Il test e il debug possono diventare difficili quando si utilizza questo design, poiché è necessario che tutti i servizi siano in esecuzione per simulare il modello di transazione.

 

Architettura

Architettura di Target

L'architettura proposta utilizza AWS Step Functions per creare uno schema a saga per prenotare voli, prenotare auto a noleggio ed elaborare i pagamenti per le vacanze.

Il seguente diagramma del flusso di lavoro illustra il flusso tipico del sistema di prenotazione viaggi. Il flusso di lavoro consiste nella prenotazione dei viaggi aerei («ReserveFlight»), nella prenotazione di un'auto («ReserveCarRental»), nell'elaborazione dei pagamenti («ProcessPayment»), nella conferma delle prenotazioni dei voli («ConfirmFlight») e nella conferma del noleggio auto («ConfirmCarRental»), seguite da una notifica di avvenuto completamento di questi passaggi. Tuttavia, se il sistema riscontra errori nell'esecuzione di una di queste transazioni, inizia a fallire all'indietro. Ad esempio, un errore nell'elaborazione dei pagamenti («ProcessPayment») attiva un rimborso («RefundPayment»), che quindi attiva la cancellazione dell'auto a noleggio e del volo («CancelRentalReservation» e «CancelFlightReservation»), che termina l'intera transazione con un messaggio di errore.

Questo modello implementa funzioni Lambda separate per ogni attività evidenziata nel diagramma, oltre a tre tabelle DynamoDB per voli, autonoleggi e pagamenti. Ogni funzione Lambda crea, aggiorna o elimina le righe nelle rispettive tabelle DynamoDB, a seconda che una transazione sia confermata o ripristinata. Il modello utilizza Amazon SNS per inviare messaggi di testo (SMS) agli abbonati, notificandoli delle transazioni non riuscite o riuscite. 

Automazione e scalabilità

È possibile creare la configurazione per questa architettura utilizzando uno dei framework IaC. Usa uno dei seguenti link per il tuo IAc preferito.

Strumenti

Servizi AWS

  • AWS Step Functions è un servizio di orchestrazione serverless che consente di combinare funzioni AWS Lambda e altri servizi AWS per creare applicazioni aziendali critiche. Attraverso la console grafica Step Functions, puoi vedere il flusso di lavoro dell'applicazione come una serie di passaggi guidati dagli eventi.

  • Amazon DynamoDB è un servizio di database NoSQL completamente gestito che offre prestazioni veloci e prevedibili con una scalabilità perfetta. Puoi utilizzare DynamoDB per creare una tabella di database in grado di archiviare e recuperare qualunque quantità di dati e soddisfare qualsiasi livello di traffico di richiesto.

  • AWS Lambda è un servizio di elaborazione che consente di eseguire codice senza effettuare il provisioning o la gestione di server. Lambda esegue il codice solo quando è necessario e si dimensiona automaticamente, da poche richieste al giorno a migliaia al secondo.

  • Amazon API Gateway è un servizio AWS per la creazione, la pubblicazione, la manutenzione, il monitoraggio e la protezione di REST, HTTP e WebSocket API su qualsiasi scala.

  • Amazon Simple Notification Service (Amazon SNS) è un servizio gestito che fornisce il recapito dei messaggi dagli editori agli abbonati.

  • AWS Cloud Development Kit (AWS CDK) è un framework di sviluppo software per definire le risorse delle applicazioni cloud utilizzando linguaggi di programmazione familiari come Python TypeScript JavaScript, Java e C#/.Net.

  • AWS Serverless Application Model (AWS SAM) Serverless Application Model (AWS) Serverless Application Model (AWS SAM) è un framework open source per la creazione di applicazioni serverless. Fornisce una sintassi abbreviata per esprimere funzioni, API, database e mappature delle sorgenti degli eventi.

Codice

Il codice per un'applicazione di esempio che dimostra il modello saga, incluso il modello IaC (AWS CDK, AWS SAM o Terraform), le funzioni Lambda e le tabelle DynamoDB, è disponibile nei seguenti link. Segui le istruzioni del primo Epic per installarli.

Epiche

AttivitàDescrizioneCompetenze richieste

Installa i pacchetti NPM.

Crea una nuova directory, accedi a quella directory in un terminale e clona il GitHub repository di tua scelta dalla sezione Codice precedente di questo schema.

Nella cartella principale che contiene il package.json file, esegui il seguente comando per scaricare e installare tutti i pacchetti Node Package Manager (NPM):

npm install
Sviluppatore, architetto cloud

Compila script.

Nella cartella principale, esegui il seguente comando per indicare al TypeScript transpiler di creare tutti i file necessari: JavaScript

npm run build
Sviluppatore, architetto cloud

Controlla le modifiche e ricompila.

Nella cartella principale, esegui il seguente comando in una finestra di terminale separata per controllare le modifiche al codice e compila il codice quando rileva una modifica:

npm run watch
Sviluppatore, architetto cloud

Esegui test unitari (solo AWS CDK).

Se utilizzi il CDK AWS, nella cartella principale, esegui il seguente comando per eseguire gli unit test di Jest:

npm run test
Sviluppatore, architetto del cloud
AttivitàDescrizioneCompetenze richieste

Distribuisci lo stack dimostrativo su AWS.

Importante: l'applicazione è indipendente dalla regione AWS. Se utilizzi un profilo, devi dichiarare la regione in modo esplicito nel profilo AWS Command Line Interface (AWS CLI) o tramite le variabili di ambiente AWS CLI.

Nella cartella principale, esegui il comando seguente per creare un assembly di distribuzione e distribuirlo nell'account e nella regione AWS predefiniti.

CDK AWS:

cdk bootstrap cdk deploy

AWS È:

sam build sam deploy --guided

Terraforma:

terraform init terraform apply

Il completamento di questo passaggio potrebbe richiedere alcuni minuti. Questo comando utilizza le credenziali predefinite configurate per l'AWS CLI.

Nota l'URL dell'API Gateway che viene visualizzato sulla console al termine della distribuzione. Avrai bisogno di queste informazioni per testare il flusso di esecuzione della saga.

Sviluppatore, architetto cloud

Confronta lo stack distribuito con lo stato attuale.

Nella cartella principale, esegui il comando seguente per confrontare lo stack distribuito con lo stato corrente dopo aver apportato modifiche al codice sorgente:

CDK AWS:

cdk diff

AWS È:

sam deploy

Terraforma:

terraform plan
Sviluppatore, architetto cloud
AttivitàDescrizioneCompetenze richieste

Metti alla prova il flusso di esecuzione della saga.

Passa all'URL dell'API Gateway che hai annotato nel passaggio precedente, quando hai distribuito lo stack. Questo URL attiva l'avvio della macchina a stati. Per ulteriori informazioni su come manipolare il flusso della macchina a stati passando diversi parametri URL, consulta la sezione Informazioni aggiuntive.

Per visualizzare i risultati, accedi alla Console di gestione AWS e vai alla console Step Functions. Qui puoi vedere ogni fase della saga state machine. Puoi anche visualizzare la tabella DynamoDB per vedere i record inseriti, aggiornati o eliminati. Se aggiorni spesso la schermata, puoi vedere lo stato della transazione cambiare da a. pending confirmed 

Puoi iscriverti all'argomento SNS aggiornando il codice nel stateMachine.ts file con il tuo numero di cellulare per ricevere messaggi SMS in caso di prenotazioni riuscite o non riuscite. Per ulteriori informazioni, consulta Amazon SNS nella sezione Informazioni aggiuntive.

Sviluppatore, architetto cloud
AttivitàDescrizioneCompetenze richieste

Pulisci le risorse.

Per pulire le risorse distribuite per questa applicazione, è possibile utilizzare uno dei seguenti comandi.

CDK AWS:

cdk destroy

AWS È:

sam delete

Terraforma:

terraform destroy
Sviluppatore di app, architetto cloud

Risorse correlate

Documenti tecnici

Documentazione del servizio AWS

Tutorial

Informazioni aggiuntive

Codice

A scopo di test, questo modello implementa API Gateway e una funzione Lambda di test che attiva la macchina a stati Step Functions. Con Step Functions, puoi controllare la funzionalità del sistema di prenotazione viaggi passando un run_type parametro per simulare gli errori in «ReserveFlightReserveCarRental,» «ProcessPayment,»,» e «ConfirmFlightConfirmCarRental.»

La funzione saga Lambda (sagaLambda.ts) riceve l'input dai parametri di query nell'URL API Gateway, crea il seguente oggetto JSON e lo passa a Step Functions per l'esecuzione:

let input = { "trip_id": tripID, //  value taken from query parameter, default is AWS request ID "depart_city": "Detroit", "depart_time": "2021-07-07T06:00:00.000Z", "arrive_city": "Frankfurt", "arrive_time": "2021-07-09T08:00:00.000Z", "rental": "BMW", "rental_from": "2021-07-09T00:00:00.000Z", "rental_to": "2021-07-17T00:00:00.000Z", "run_type": runType // value taken from query parameter, default is "success" };

È possibile sperimentare diversi flussi della macchina a stati Step Functions passando i seguenti parametri URL:

  • Esecuzione riuscita ─ https://{api gateway url}

  • Reserve Flight Fail ─ https://{api gateway url}? RunType= failFlightsReservation

  • Conferma il fallimento del volo ─ https://{api gateway url}? RunType= failFlightsConfirmation

  • Reserve Car Rental Failure ─ https://{api gateway url}? RunType= Prenotazione failCarRental

  • Conferma il fallimento del noleggio auto ─ https://{api gateway url}? RunType= failCarRental Conferma

  • Processo di pagamento non riuscito ─ https://{api gateway url}? RunType=FailPayment

  • Passa un Trip ID ─ https://{api gateway url}? tripId= {per impostazione predefinita, l'ID del viaggio sarà l'ID della richiesta AWS}

modelli IaC

Gli archivi collegati includono modelli IaC che è possibile utilizzare per creare l'intera applicazione di prenotazione viaggi di esempio.

Tabelle DynamoDB

Ecco i modelli di dati per le tabelle dei voli, degli autonoleggi e dei pagamenti.

Flight Data Model: var params = { TableName: process.env.TABLE_NAME, Item: { 'pk' : {S: event.trip_id}, 'sk' : {S: flightReservationID}, 'trip_id' : {S: event.trip_id}, 'id': {S: flightReservationID}, 'depart_city' : {S: event.depart_city}, 'depart_time': {S: event.depart_time}, 'arrive_city': {S: event.arrive_city}, 'arrive_time': {S: event.arrive_time}, 'transaction_status': {S: 'pending'} } }; Car Rental Data Model: var params = { TableName: process.env.TABLE_NAME, Item: { 'pk' : {S: event.trip_id}, 'sk' : {S: carRentalReservationID}, 'trip_id' : {S: event.trip_id}, 'id': {S: carRentalReservationID}, 'rental': {S: event.rental}, 'rental_from': {S: event.rental_from}, 'rental_to': {S: event.rental_to}, 'transaction_status': {S: 'pending'} } }; Payment Data Model: var params = { TableName: process.env.TABLE_NAME, Item: { 'pk' : {S: event.trip_id}, 'sk' : {S: paymentID}, 'trip_id' : {S: event.trip_id}, 'id': {S: paymentID}, 'amount': {S: "750.00"}, // hard coded for simplicity as implementing any monetary transaction functionality is beyond the scope of this pattern 'currency': {S: "USD"}, 'transaction_status': {S: "confirmed"} } };

Funzioni Lambda

Verranno create le seguenti funzioni per supportare il flusso e l'esecuzione della macchina a stati in Step Functions:

  • Reserve Flights: inserisce un record nella tabella DynamoDB Flights con transaction_status un pending di, per prenotare un volo.

  • Confirm Flight: aggiorna il record nella tabella DynamoDB Flights, da transaction_status impostare su, per confermare confirmed il volo.

  • Annulla prenotazione voli: elimina il record dalla tabella DynamoDB Flights, per annullare il volo in sospeso.

  • Reserve Car Rentals: inserisce un record nella tabella CarRentals DynamoDB con transaction_status un pending di, per prenotare un noleggio auto.

  • Conferma noleggio auto: aggiorna il record nella tabella CarRentals DynamoDB, transaction_status impostandolo su, per confermare confirmed il noleggio auto.

  • Annulla prenotazione noleggio auto: elimina il record dalla tabella CarRentals DynamoDB, per annullare il noleggio auto in sospeso.

  • Elabora pagamento: inserisce un record nella tabella Pagamenti di DynamoDB per il pagamento.

  • Annulla pagamento: elimina il record del pagamento dalla tabella DynamoDB Payments.

Amazon SNS

L'applicazione di esempio crea il seguente argomento e sottoscrizione per l'invio di messaggi SMS e la notifica al cliente in caso di prenotazioni riuscite o non riuscite. Se desideri ricevere messaggi di testo durante il test dell'applicazione di esempio, aggiorna l'abbonamento SMS con il tuo numero di telefono valido nel file di definizione della macchina a stati.

Frammento di CDK AWS (aggiungi il numero di telefono nella seconda riga del codice seguente):

const topic = new  sns.Topic(this, 'Topic'); topic.addSubscription(new subscriptions.SmsSubscription('+11111111111')); const snsNotificationFailure = new tasks.SnsPublish(this ,'SendingSMSFailure', { topic:topic, integrationPattern: sfn.IntegrationPattern.REQUEST_RESPONSE, message: sfn.TaskInput.fromText('Your Travel Reservation Failed'), });   const snsNotificationSuccess = new tasks.SnsPublish(this ,'SendingSMSSuccess', { topic:topic, integrationPattern: sfn.IntegrationPattern.REQUEST_RESPONSE, message: sfn.TaskInput.fromText('Your Travel Reservation is Successful'), });

Snippet AWS SAM (sostituisci le +1111111111 stringhe con il tuo numero di telefono valido):

StateMachineTopic11111111111: Type: 'AWS::SNS::Subscription' Properties: Protocol: sms TopicArn: Ref: StateMachineTopic Endpoint: '+11111111111' Metadata: 'aws:sam:path': SamServerlessSagaStack/StateMachine/Topic/+11111111111/Resource

Snippet Terraform (sostituisci la +111111111 stringa con il tuo numero di telefono valido):

resource "aws_sns_topic_subscription" "sms-target" { topic_arn = aws_sns_topic.topic.arn protocol = "sms" endpoint = "+11111111111" }

Prenotazioni riuscite

Il seguente flusso illustra una prenotazione riuscita con «ReserveFlight,»» e «ReserveCarRentalProcessPayment» seguiti da «ConfirmFlight» e «ConfirmCarRental.» Il cliente viene informato dell'avvenuta prenotazione tramite messaggi SMS che vengono inviati all'abbonato dell'argomento SNS.

Prenotazioni non riuscite

Questo flusso è un esempio di fallimento dello schema della saga. Se, dopo aver prenotato voli e auto a noleggio, «ProcessPayment» fallisce, i passaggi vengono annullati in ordine inverso.  Le prenotazioni vengono rilasciate e il cliente viene informato dell'errore tramite messaggi SMS inviati all'abbonato dell'argomento SNS.