Event sourcing met microservices

2020-01-15

Gedurende een deep dive in microservices -en event driven architecturen liep ik hier tegen aan.

Event sourcing bestaat al geruime tijd maar kan erg handig zijn bij de ontwikkeling van microservices. Hierbij heb je t.o.v. een monolite vaak geen gedeelde database. Aanbevolen wordt dat elke microservice zijn eigen database heeft of beter gezegd: zijn eigen data heeft dat alleen beschikbaar is door gebruik te maken van de API van de service. Om op deze manier de data (de state van de microservice) op een goede manier te kunnen encapsuleren.

De domein modellen zijn gedistribueerd over verschillende microservices. Dit komt lose coupling ten goede.

 


Ok, maar als in mijn applicatie alles verdeeld is over verschillende microservices met ieder een eigen database hoe garandeer ik dan data consistentie bij distributed transactions?

Een event georiënteerde aanpak voor het opslaan van je domein objecten (event sourcing) kan hierbij helpen. Je slaat dus niet (enkel) de huidige state op maar eerder de aanleiding. De microservice haakt als het ware in op deze event store en benaderd op basis van de gebeurtenissen die de events beschrijven de huidige state.

Deze aanpak is niet in lijn met de traditionele manier van opslaan van de domein objecten, in bijvoorbeeld (rationele) databases. Namelijk in plaats van het opslaan van de huidige state sla je de belangrijke gebeurtenissen als events op waardoor de huidige state van de domein objecten wijzigt. Tip: neem zo nu dan een keer een snapshot zodat de microservices niet bij elke startup alle events hoeft in te laden.

Het enkel opslaan van de belangrijke gebeurtenissen zal in eerste instantie waarschijnlijk niet je eerste keus zijn, net zoals dat van je teamleden. Je zal waarschijnlijk dan ook met een goed verhaal moeten komen.

Wanneer is deze event georiënteerde aanpak een goed idee?

Het is een event gebaseerde aanpak voor het persistent maken van je domein gebeurtenissen (events) wat de volgende voordelen heeft;

- Je kan een stream van events genereren wat de data consistentie problematiek bij microservices, zoals eerder genoemd, oplost, mocht dit aan de orde zijn.

- Het event publicatie mechanisme dat je hiervoor gebruikt zorgt er voor dat wanneer er iets gebeurt in je applicatie, dat er dan een event wordt gepubliceerd waar bijvoorbeeld data analyse door gevoed kan worden of waarmee gebruikers genotificeerd kunnen worden.

- Elke state verandering van de applicatie wordt gerechtvaardigd door een event, je hebt hierdoor 100% betrouwbare logging.

- Omdat de volledige geschiedenis van elk domein object wordt opgeslagen kan je ook terug gaan in de tijd en bepalen wat de state van een domein object was op elk tijdstip. Dit kan relevant zijn in sommige zwaar gereguleerde omgevingen waar informatie zoals 'wie deed wat en wanneer' erg belangrijk is. Dit maakt het gedrag van je applicatie reproduceerbaar door het opnieuw kunnen 'afspelen' van gebeurtenissen om een bepaalde state te kunnen bereiken.

- Het maken (en onderhouden) van domain model - relationele database mappings is overbodig.

- Je hebt een complete set aan geschiedenis van alles wat er is gebeurt in het systeem vanaf het begin. Dus wanneer je vandaag een service maakt die een nieuwe feature implementeert dan kan deze gevoed worden met alle gebeurtenissen uit het verleden. Deze service gaat zich dan gedragen alsof deze al draait vanaf het begin. Hetzelfde principe gaat op als de service een tijdje offline is geweest.

En wanneer is deze aanpak misschien een iets minder goed idee?

- Deze aanpak vereist een rewrite van je applicatie omdat het een andere manier is om de core business logic te structureren.

- Het is een beetje vreemde en onbekende manier om je business logic te structureren wat potentieel een steile learning curve met zich meebrengt. Echter bestaat event sourcing al een tijdje en is het onderdeel van de DDD (Domain Driven Design) community. Er is dus veel hulpmateriaal beschikbaar.

- Omdat de opgeslagen events blijven bestaan bestaat de kans dat je voor altijd last blijft houden van slecht ontworpen events uit het verleden. Hou daarom de events simpel.

- Je microservices zijn vatbaar voor dubbele events. Maak je microservices daarom idempotent (kan overweg met meerdere keren dezelfde vraag of commando) of zorg voor filtering op dubbele events. Lijkt mij redelijk straith forward.

- Het opvragen van de (huidige) state van een domein object is een stuk lastiger geworden. Als je bijvoorbeeld op zoek bent naar alle domein objecten die voldoen aan een bepaalde voorwaarde, dan zal je query op een of andere manier alle events moeten combineren. Dit kan erg complex en inefficiënt worden.

 

Mocht je benieuwd zijn naar wat event sourcing voor jouw project zou kunnen betekenen, lees dan eens dit stuk van Martin Fowler door.

 

Werken bij Infiniot?

Heeft deze blog jou geïnspireerd om ook een bijdrage te leveren aan de energietransitie in Nederland? Goed nieuws! We zijn altijd op zoek naar nieuwe collega’s om ons team te versterken! Bekijk hier onze vacature Software Engineer.


Bekijk alle posts van Bob