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à.
Modello di origine evento
Intento
Nelle architetture basate sugli eventi, il modello di approvvigionamento degli eventi memorizza gli eventi che determinano un cambiamento di stato in un datastore. Ciò consente di acquisire e mantenere una cronologia completa dei cambiamenti di stato e promuove la verificabilità, la tracciabilità e la capacità di analizzare gli stati passati.
Motivazione
Più microservizi possono collaborare per gestire le richieste e comunicare attraverso eventi. Questi eventi possono comportare un cambiamento di stato (dati). La memorizzazione degli oggetti evento nell'ordine in cui si presentano fornisce informazioni preziose sullo stato corrente dell'entità dati e informazioni aggiuntive su come è arrivata a tale stato.
Applicabilità
Utilizza il modello di approvvigionamento degli eventi quando:
-
Per il tracciamento è necessaria una cronologia immutabile degli eventi che si verificano in un'applicazione.
-
Le proiezioni di dati poliglotti sono necessarie da un'unica fonte di verità (SSOT).
-
È necessaria la ricostruzione temporale dello stato dell'applicazione.
-
L'archiviazione a lungo termine dello stato dell'applicazione non è richiesta, ma è possibile ricostruirla secondo necessità.
-
I carichi di lavoro hanno volumi di lettura e scrittura diversi. Ad esempio, hai carichi di lavoro ad alta intensità di scrittura che non richiedono l'elaborazione in tempo reale.
-
È necessaria l'acquisizione dei dati di modifica per analizzare le prestazioni dell'applicazione e altri parametri.
-
Sono necessari i dati di audit per tutti gli eventi che si verificano in un sistema a fini di reporting e conformità.
-
Si desidera ricavare scenari ipotetici modificando (inserendo, aggiornando o eliminando) gli eventi durante il processo di riproduzione per determinare il possibile stato finale.
Problemi e considerazioni
-
Controllo ottimistico della concorrenza: questo modello memorizza ogni evento che causa un cambiamento di stato nel sistema. Più utenti o servizi possono provare ad aggiornare lo stesso dato contemporaneamente, causando collisioni di eventi. Queste collisioni si verificano quando vengono creati e applicati contemporaneamente eventi in conflitto, il che si traduce in uno stato finale dei dati che non corrisponde alla realtà. Per risolvere questo problema, puoi implementare strategie per rilevare e risolvere le collisioni di eventi. Ad esempio, è possibile implementare uno schema ottimistico di controllo della concorrenza includendo il controllo delle versioni o aggiungendo timestamp agli eventi per tenere traccia dell'ordine degli aggiornamenti.
-
Complessità: l'implementazione dell'approvvigionamento degli eventi richiede un cambiamento di mentalità dalle tradizionali operazioni CRUD a un modo di pensare basato sugli eventi. Il processo di riproduzione, utilizzato per ripristinare il sistema allo stato originale, può essere complesso per garantire l'idempotenza dei dati. L'archiviazione degli eventi, i backup e gli snapshot possono inoltre aggiungere ulteriore complessità.
-
Coerenza finale: le proiezioni dei dati derivate dagli eventi sono in ultima analisi coerenti a causa della latenza nell'aggiornamento dei dati mediante il modello CQRS (Command Query Responsibility Segregation) o le viste materializzate. Quando i consumer elaborano i dati da un archivio eventi e gli editori inviano nuovi dati, la proiezione dei dati o l'oggetto dell'applicazione potrebbero non rappresentare lo stato corrente.
-
Interrogazione: il recupero di dati correnti o aggregati dai log degli eventi può essere più complesso e più lento rispetto ai database tradizionali, in particolare per query e attività di reporting complesse. Per mitigare questo problema, l'approvvigionamento degli eventi viene spesso implementato con il modello CQRS.
-
Dimensioni e costo dell'archivio eventi: l'archivio eventi può registrare una crescita esponenziale delle dimensioni man mano che gli eventi persistono continuamente, specialmente nei sistemi che hanno un numero elevato di eventi o periodi di conservazione prolungati. Di conseguenza, è necessario archiviare periodicamente i dati degli eventi in uno spazio di archiviazione conveniente per evitare che l'archivio eventi diventi troppo grande.
-
Scalabilità dell'archivio eventi: l'archivio eventi deve gestire in modo efficiente volumi elevati di operazioni di scrittura e lettura. La scalabilità di un archivio eventi può essere difficile, quindi è importante disporre di un datastore che fornisca frammenti e partizioni.
-
Efficienza e ottimizzazione: scegli o progetta un archivio eventi che gestisca le operazioni di scrittura e lettura in modo efficiente. L'archivio eventi deve essere ottimizzato per il volume di eventi e i modelli di query previsti per l'applicazione. L'implementazione di meccanismi di indicizzazione e interrogazione può accelerare il recupero degli eventi durante la ricostruzione dello stato dell'applicazione. È inoltre possibile prendere in considerazione l'utilizzo di database o librerie specializzati in archivi di eventi che offrono funzionalità di ottimizzazione delle query.
-
Snapshot: è necessario eseguire il backup dei log degli eventi a intervalli regolari con attivazione basata sul tempo. La riproduzione degli eventi sull'ultimo backup dei dati riuscito noto dovrebbe portare al ripristino puntuale dello stato dell'applicazione. L'obiettivo del punto di ripristino (RPO) è il periodo di tempo massimo accettabile dall'ultimo punto di ripristino dei dati. L'RPO determina ciò che viene considerato una perdita di dati accettabile tra l'ultimo punto di ripristino e l'interruzione del servizio. La frequenza degli snapshot giornalieri del datastore e dell'archivio eventi deve essere basata sull'RPO dell'applicazione.
-
Sensibilità temporale: gli eventi vengono archiviati nell'ordine in cui si verificano. Pertanto, quando si implementa questo modello l'affidabilità della rete è un fattore importante da considerare. I problemi di latenza possono portare a uno stato errato del sistema. Utilizza le code FIFO (first in, first out) con consegna al massimo una volta per portare gli eventi all'archivio eventi.
-
Prestazioni della riproduzione degli eventi: la riproduzione di un numero considerevole di eventi per ricostruire lo stato corrente dell'applicazione può richiedere molto tempo. Sono necessari sforzi di ottimizzazione per migliorare le prestazioni, in particolare quando si riproducono gli eventi dai dati archiviati.
-
Aggiornamenti di sistema esterni: le applicazioni che utilizzano il modello di approvvigionamento degli eventi potrebbero aggiornare i datastore in sistemi esterni e acquisire questi aggiornamenti come oggetti evento. Durante le riproduzioni degli eventi, questo potrebbe diventare un problema se il sistema esterno non prevede un aggiornamento. In questi casi, è possibile utilizzare i flag di funzionalità per controllare gli aggiornamenti di sistema esterni.
-
Interrogazioni di sistemi esterni: quando le chiamate ai sistemi esterni sono sensibili alla data e all'ora della chiamata, i dati ricevuti possono essere archiviati in datastore interni per essere utilizzati durante le riproduzioni.
-
Controllo delle versioni degli eventi: man mano che l'applicazione si evolve, la struttura degli eventi (modello) può cambiare. È quindi necessaria l'implementazione di una strategia di controllo delle versioni degli eventi per garantire la compatibilità con le versioni precedenti e successive. Ciò può comportare l'inclusione di un campo di versione nel payload dell'evento e la gestione appropriata delle diverse versioni dell'evento durante la riproduzione.
Implementazione
Architettura di alto livello
Comandi ed eventi
Nelle applicazioni di microservizi distribuite e basate sugli eventi, i comandi rappresentano le istruzioni o le richieste inviate a un servizio, in genere con l'intento di avviare una modifica del suo stato. Il servizio elabora questi comandi e valuta la validità e l'applicabilità del comando allo stato corrente. Se il comando viene eseguito correttamente, il servizio risponde emettendo un evento che indica l'azione intrapresa e le informazioni pertinenti sullo stato. Ad esempio, nel diagramma seguente, il servizio di prenotazione risponde al comando Book ride (Prenota corsa) emettendo l'evento Ride booked (Corsa prenotata).
![Comandi ed eventi nel modello di approvvigionamento degli eventi](images/event-sourcing-1.png)
Archivi di eventi
Gli eventi vengono registrati in un repository o datastore immutabile, di sola aggiunta e ordinato cronologicamente, noto come archivio eventi Ogni modifica di stato viene trattata come un singolo oggetto evento. È possibile ricostruire un oggetto di entità o un datastore con uno stato iniziale noto, lo stato corrente e qualsiasi visualizzazione temporale ripetendo gli eventi nell'ordine in cui si sono verificati.
L'archivio eventi funge da registrazione storica di tutte le azioni e i cambiamenti di stato e funge da preziosa fonte di informazioni. È possibile utilizzare l'archivio eventi per derivare lo stato finale e aggiornato del sistema passando gli eventi attraverso un processore di riproduzione, che applica questi eventi per produrre una rappresentazione accurata dello stato più recente del sistema. È inoltre possibile utilizzare l'archivio eventi per generare la prospettiva puntuale dello stato ripetendo gli eventi tramite un processore di riproduzione. Nel modello di approvvigionamento degli eventi, lo stato corrente potrebbe non essere interamente rappresentato dall'oggetto evento più recente. Puoi derivare lo stato corrente in uno dei seguenti tre modi:
-
Aggregando gli eventi correlati. Gli oggetti evento correlati vengono combinati per generare lo stato corrente per l'interrogazione. Questo approccio viene spesso utilizzato insieme al modello CQRS, in quanto gli eventi vengono combinati e scritti nel datastore di sola lettura.
-
Utilizzando le viste materializzate. È possibile utilizzare l'approvvigionamento degli eventi con il modello della vista materializzata per calcolare o riepilogare i dati degli eventi e ottenere lo stato corrente dei dati correlati.
-
Riproducendo gli eventi. Gli oggetti evento possono essere riprodotti per eseguire azioni volte a generare lo stato corrente.
Il diagramma seguente mostra l'evento Ride booked
archiviato in un archivio eventi.
![Utilizzo degli archivi di eventi nel modello di approvvigionamento degli eventi](images/event-sourcing-2.png)
L'archivio eventi pubblica gli eventi che memorizza e gli eventi possono essere filtrati e indirizzati al processore appropriato per le azioni successive. Ad esempio, gli eventi possono essere indirizzati a un processore di visualizzazione che riepiloga lo stato e mostra una vista materializzata. Gli eventi vengono trasformati nel formato di dati del datastore di destinazione. Questa architettura può essere estesa per derivare diversi tipi di datastore, il che porta alla persistenza poliglotta dei dati.
Il diagramma seguente descrive gli eventi in un'applicazione di prenotazione di una corsa auto. Tutti gli eventi che si verificano all'interno dell'applicazione vengono archiviati nell'archivio eventi. Gli eventi memorizzati vengono quindi filtrati e indirizzati a diversi consumer.
![Esempio di implementazione di alto livello per il modello di approvvigionamento degli eventi](images/event-sourcing-3.png)
Gli eventi della corsa possono essere utilizzati per generare datastore di sola lettura utilizzando il CQRS o il modello della vista materializzata. Puoi ottenere lo stato attuale della corsa, il conducente o la prenotazione interrogando gli archivi di lettura. Alcuni eventi, come Location changed
o Ride completed
, vengono pubblicati su un altro consumer per l'elaborazione dei pagamenti. Una volta completata la corsa, tutti gli eventi della corsa vengono riprodotti per creare una cronologia della corsa a scopo di controllo o rendicontazione.
Il modello di approvvigionamento degli eventi viene spesso utilizzato in applicazioni che richiedono un ripristino puntuale e anche quando i dati devono essere proiettati in formati diversi utilizzando un'unica fonte di verità. Entrambe queste operazioni richiedono un processo di ripetizione per eseguire gli eventi e determinare lo stato finale richiesto. Il processore di riproduzione potrebbe inoltre richiedere un punto di partenza noto, idealmente non all'avvio dell'applicazione, perché non sarebbe un processo efficiente. Si consiglia di acquisire snapshot regolari dello stato del sistema e di applicare un numero inferiore di eventi per ricavare uno stato aggiornato.
Implementazione tramite servizi AWS
Nella seguente architettura, il flusso di dati Amazon Kinesis viene utilizzato come archivio eventi. Questo servizio acquisisce e gestisce le modifiche delle applicazioni sotto forma di eventi e offre una soluzione di streaming di dati ad alta velocità di trasmissione effettiva e in tempo reale. Per implementare il modello di approvvigionamento degli eventi su AWS, puoi anche utilizzare servizi come Amazon EventBridge e Streaming gestito da Amazon per Apache Kafka (Amazon MSK) in base alle esigenze della tua applicazione.
Per migliorare la durabilità e abilitare il controllo, puoi archiviare gli eventi acquisiti dal flusso di dati Kinesis in Amazon Simple Storage Service (Amazon S3). Questo approccio a doppia archiviazione aiuta a conservare i dati storici degli eventi in modo sicuro per future analisi e scopi di conformità.
![Implementazione del modello di approvvigionamento degli eventi con i servizi AWS](images/event-sourcing-4.png)
Il flusso di lavoro consiste nei seguenti passaggi:
-
Una richiesta di prenotazione della corsa viene effettuata tramite un client mobile verso un endpoint Gateway Amazon API.
-
Il microservizio della corsa (funzione
Ride service
Lambda) riceve la richiesta, trasforma gli oggetti e li pubblica sul flusso di dati Kinesis. -
I dati degli eventi nel flusso di dati Kinesis vengono archiviati in Amazon S3 a scopo di conformità e cronologia degli audit.
-
Gli eventi vengono trasformati ed elaborati dalla funzione
Ride event processor
Lambda e archiviati in un database Amazon Aurora per fornire una vista materializzata dei dati della corsa. -
Gli eventi della corsa completati vengono filtrati e inviati per l'elaborazione dei pagamenti a un gateway di pagamento esterno. Una volta completato il pagamento, viene inviato un altro evento al flusso di dati Kinesis per aggiornare il database Ride (Corse).
-
Al termine della corsa, gli eventi di viaggio vengono riprodotti nella funzione
Ride service
Lambda per creare i percorsi e la cronologia della corsa. -
Le informazioni sulla corsa possono essere lette tramite il
Ride data service
, che legge dal database Aurora.
Gateway API può anche inviare l'oggetto evento direttamente al flusso di dati Kinesis senza la funzione Ride service
Lambda. Tuttavia, in un sistema complesso come un servizio di ride hailing, potrebbe essere necessario elaborare e arricchire l'oggetto evento prima di inserirlo nel flusso di dati. Per questo motivo, l'architettura dispone di un Ride service
che elabora l'evento prima di inviarlo al flusso di dati Kinesis.