Il SAGA Pattern è utilissimo in tutti i sistemi a transazioni distribuite: una saga altro non è che una sequenza di transazioni locali al completamento delle quali viene pubblicato un messaggio o un evento per attivare la catena successiva. L'obiettivo è quindi garantire l'integrità del dato e gestire eventuali operazioni compensative nel caso in cui singoli passaggi abbiano esito negativo.
E' importante sottolineare che una transazione locale è il lavoro atomico svolto da ciascun partecipante alla saga. In questa sequenza di operazioni, ciascun componente aggiorna il proprio database ed innesca le operazioni successive solo nel caso in cui la transazione locale non generi un'eccezione.
Il classico esempio in letteratura è quello che prevede la presenza di 3 microservizi nell'ambito di un e-commerce:
- il servizio che gestisce la creazione dell'ordine
- il servizio che si occupa dei pagamenti e delle transazioni con la banca
- il servizio che si occupa della movimentazione del magazzino
Esistono due modi per implementare il SAGA Pattern, ma in questo articolo tratteremo unicamente la versione Orchestration, la quale - come si evince dal nome - prevede la presenza di un orchestratore il quale comunica ai vari servizi cosa fare e quando fare una determinata attività.
La variante Event/Coreography, solo per fornire un piccolo cenno, comporta che ogni servizio sia in grado di produrre e ricevere eventi, di comprendere quale sia di sua competenza innescando una catena di successive azioni a cascata.
Ritornando all'esempio del negozio elettronico di cui sopra, avremmo una sequenza del tipo:
- Il servizio online invoca il servizio Ordine che si occupa della creazione di un nuovo ordine in stato "Pending" e manda un comando Create_Order all’orchestratore per avviare una transazione.
- L’orchestratore invia un comando Execute_Payment_Command al servizio Pagamenti che risponde con un messaggio "Pagamento eseguito".
- L’orchestratore invia un comando Execute_Order_Command al servizio Magazzino che risponde con il messaggio "Spedizione eseguita".
- Alla fine l’orchestratore manda il comando Complete_Order al servizio Ordine che cambia lo stato dell’ordine in "Completo".
Tutto abbastanza intuitivo in questo happy flow....ma cosa accade se uno dei servizi solleva un'eccezione generando la necessità di una rollback della transazione?
Ed ecco che ritornando allo shop online, nel caso in cui il servizio magazzino rispondesse con un errore del tipo "prodotto esaurito", l'orchestratore invierebbe le istruzioni alle altri componenti, chiedendo ad esempio di annullare l'ordine ed effettuare un rimborso al cliente associato all'ordine in questione.
Non è tutto oro quello che luccica: uno dei principali rischi derivanti dall'approccio Orchestration è quello di concentrare troppa logica, difatti, nell'orchestratore al punto di creare un vero e proprio collo di bottiglia all'interno dell'architettura. Tuttavia, i vantaggi sono evidenti: si riduce molto la complessità dell'intero sistema in quanto i microservizi rispondono ai comandi proveniente dal motore centrale ma non invocano mai l'orchestratore evitando dipendenze cicliche; inoltre, come detto poc'anzi, la gestione delle transazioni risulta molto facile così come le corrispondenti azioni compensative.
Questo articolo vuole essere unicamente un'introduzione alla tematica. Nelle prossime settimane seguiranno ulteriori post in cui metteremo mano al codice ed affronteremo le problematiche sopra discusse.
Comments
Post a Comment