<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Eventual Consistency &#8211; Smals Research</title>
	<atom:link href="https://www.smalsresearch.be/tag/eventual-consistency/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.smalsresearch.be</link>
	<description></description>
	<lastBuildDate>Thu, 26 Mar 2026 14:13:36 +0000</lastBuildDate>
	<language>en-GB</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>

<image>
	<url>https://www.smalsresearch.be/wp-content/uploads/2026/01/cropped-cropped-Smals_Research-32x32.png</url>
	<title>Eventual Consistency &#8211; Smals Research</title>
	<link>https://www.smalsresearch.be</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Méér EDA: stap voor stap Programmeren</title>
		<link>https://www.smalsresearch.be/meer-eda-stap-voor-stap-programmeren/</link>
					<comments>https://www.smalsresearch.be/meer-eda-stap-voor-stap-programmeren/#comments</comments>
		
		<dc:creator><![CDATA[Koen Vanderkimpen]]></dc:creator>
		<pubDate>Thu, 07 Dec 2023 13:30:35 +0000</pubDate>
				<category><![CDATA[[NL]]]></category>
		<category><![CDATA[Blog post]]></category>
		<category><![CDATA[development]]></category>
		<category><![CDATA[EDA]]></category>
		<category><![CDATA[Event]]></category>
		<category><![CDATA[Eventual Consistency]]></category>
		<category><![CDATA[methodology]]></category>
		<category><![CDATA[software design]]></category>
		<category><![CDATA[software engineering]]></category>
		<guid isPermaLink="false">/?p=19610</guid>

					<description><![CDATA[De voordelen van het gebruik van EDA zijn legio. Maar hoe gebruik je nu eigenlijk EDA in de praktijk? Wat als je al een enorm ecosysteem van toepassingen hebt die enkel en alleen via synchrone communicatie worden geïntegreerd en je nog nagenoeg geen business Events publiceert? In deze blog-post stellen we een methode voor om [&#8230;]]]></description>
										<content:encoded><![CDATA[
<figure class="wp-block-image alignleft size-full is-resized"><a href="/wp-content/uploads/2022/12/EDA.png"><img fetchpriority="high" decoding="async" width="569" height="491" src="/wp-content/uploads/2022/12/EDA.png" alt="" class="wp-image-17967" style="width:153px;height:auto" srcset="https://www.smalsresearch.be/wp-content/uploads/2022/12/EDA.png 569w, https://www.smalsresearch.be/wp-content/uploads/2022/12/EDA-300x259.png 300w" sizes="(max-width: 569px) 100vw, 569px" /></a></figure>



<p class="justify-text">De voordelen van het gebruik van EDA zijn legio. Maar hoe gebruik je nu eigenlijk EDA in de praktijk? Wat als je al een enorm ecosysteem van toepassingen hebt die enkel en alleen via synchrone communicatie worden geïntegreerd en je nog nagenoeg geen business Events publiceert? In deze blog-post stellen we een methode voor om een applicatie te laten evolueren om meer Events te gaan publiceren.</p>



<span id="more-19610"></span>



<p></p>



<p class="justify-text">Binnen de instellingen van de Sociale Zekerheid groeit het besef dat <a href="/de-vier-gezichten-van-eda/" data-type="post" data-id="17574">Event Driven Architecture</a> (EDA) erg nuttig kan zijn als onderdeel van de integratiestrategie (we hebben hierover reeds uitvoerig geblogd en de belangrijkste voordelen zijn ook samengevat in ons <a href="/webinar-eda/" data-type="post" data-id="19311">webinar van november</a>). We hebben in ons IT ecosysteem echter al een enorm groot aantal systemen en applicaties die hier nog niet noodzakelijk van gebruik maken. Het zou zonde zijn als we ons voor EDA enkel zouden focussen op nieuwe toepassingen &#8211; de belangrijkste business Events in het ecosysteem worden waarschijnlijk al gecapteerd door reeds bestaande diensten. Maar hoe kunnen we er dan voor zorgen dat deze Events effectief via EDA technologie &#8211; als effectieve IT Events &#8211; worden gepubliceerd en beschikbaar worden in het ecosysteem voor subscribers?</p>



<p class="justify-text">In deze blog zullen we een mogelijke stap voor stap benadering bekijken, waarmee we reeds bestaande toepassingen meer Event-Driven kunnen maken. Niet alleen maar door ze stelselmatig meer Events te laten publiceren (al zal dit een logische eerste stap zijn), maar ook door ze hun eigen Events te laten gebruiken.</p>



<p class="justify-text">Een noodzakelijke disclaimer hier, is dat het Event-Driven maken van toepassingen niet het enige is dat zal moeten gebeuren om te evolueren naar een ecosysteem met een ruim en matuur gebruik van EDA. Wat dit allemaal zou moeten inhouden (b.v. het opzetten van een goede Event Broker), staat momenteel nog ter discussie in onze innovatiewerkgroep, al kunnen we daaromtrent uiteraard onze mening geven in een toekomstige blog-post&#8230;</p>



<h2 class="wp-block-heading">Fase 1: Event-Publicatie, &#8220;Na de Feiten&#8221;</h2>



<p class="justify-text">De eerste stap in het refactoren van een bestaande toepassing is meteen ook de belangrijkste voor het ecosysteem: het publiceren van Events. We moeten dit in eerste instantie als een zuivere toevoeging aan de functionaliteiten beschouwen, zonder enige impact op de reeds bestaande. Daarom zullen we een Event pas publiceren &#8220;na de feiten&#8221;, i.e. nadat alle zaken die normaal gezien door de toepassing worden gedaan, reeds zijn uitgevoerd.</p>



<figure class="wp-block-image aligncenter size-full"><a href="/wp-content/uploads/2023/12/fase1.png"><img decoding="async" width="915" height="430" src="/wp-content/uploads/2023/12/fase1.png" alt="" class="wp-image-19614" srcset="https://www.smalsresearch.be/wp-content/uploads/2023/12/fase1.png 915w, https://www.smalsresearch.be/wp-content/uploads/2023/12/fase1-300x141.png 300w, https://www.smalsresearch.be/wp-content/uploads/2023/12/fase1-768x361.png 768w" sizes="(max-width: 915px) 100vw, 915px" /></a><figcaption class="wp-element-caption">Figuur 1: Een Event publiceren na al het andere werk.</figcaption></figure>



<p class="justify-text">Laten we kijken hoe we dit kunnen doen voor één Event (we kunnen dit uiteraard herhalen om de toepassing meerdere Events te laten publiceren). Beschouw het (informele) sequentiediagram in Fig. 1: een  bepaald commando komt binnen in de toepassing (normaal gezien <a href="/data-centric-it-met-rest/" data-type="post" data-id="9535">via een API</a>), en er is besloten dat dit aanleiding geeft tot het voorkomen van een bepaald business Event; we willen dit Event dan ook publiceren als gevolg van het ontvangen commando. De toepassing doet reeds ander werk (&#8220;Internal Work&#8221;) als gevolg van het commando, en het commando moet worden beschouwd als een transactie (zoals we zien in &#8220;Command Transaction&#8221;).</p>



<p class="justify-text">Om het Event te publiceren met een minimale impact op de werking van de toepassing, zullen we het (via het &#8220;EDA Subsystem&#8221;) publiceren nadat we de transactie hebben vervolledigd. In de praktijk zal dit b.v. kunnen door (bínnen de transactie) een extra taak in de toepassing te creëren in een aparte thread, die pas wordt uitgevoerd nadat de transactie is afgewerkt (de &#8220;publicatietaak&#8221;). Het creëren van deze taak zal een zo eenvoudig mogelijke instructie zijn in de programmatie, met een veel kleinere kans op falen dan het effectieve uitvoeren van de taak, en kunnen we daarom dus veilig binnen de transactie doen.</p>



<p class="justify-text">Wanneer dan, achteraf, de publicatietaak effectief wordt uitgevoerd, zal dit door het EDA subsysteem gebeuren, en zullen we dan effectief het Event publiceren (in eerste instantie kan dit als &#8220;mock&#8221;: een operatie zonder enig effect, later zullen we het Event effectief aanbieden aan de Event Broker). Aldus komt het Event terecht in het ecosysteem en kan men het nuttig beginnen gebruiken.</p>



<h2 class="wp-block-heading">Fase 2: Event-Publicatie, &#8220;In Transactie&#8221;</h2>



<p class="justify-text">In fase 1 hebben we, om een zo min mogelijke impact te hebben op de performantie en kans op falen van de transactie, een nogal gekunstelde manier moeten gebruiken om het Event te publiceren búiten de transactie om. Een logische volgende stap is dan ook om het publiceren van het Event onderdeel te laten uitmaken van de transactie. Bijgevolg zullen we dan ook garanderen dat, indien de transactie volledig wordt uitgevoerd, het Event ook wordt gepubliceerd. Dit kan een garantie zijn van groot belang voor de Event subscribers verderop in het ecosysteem, vanaf nu kan men erop rekenen dat álle Events van dat type de revue zullen passeren.</p>



<figure class="wp-block-image aligncenter size-full"><a href="/wp-content/uploads/2023/12/fase2.png"><img decoding="async" width="1007" height="509" src="/wp-content/uploads/2023/12/fase2.png" alt="" class="wp-image-19616" srcset="https://www.smalsresearch.be/wp-content/uploads/2023/12/fase2.png 1007w, https://www.smalsresearch.be/wp-content/uploads/2023/12/fase2-300x152.png 300w, https://www.smalsresearch.be/wp-content/uploads/2023/12/fase2-768x388.png 768w" sizes="(max-width: 1007px) 100vw, 1007px" /></a><figcaption class="wp-element-caption">Figuur 2: Event publiceren als deel van het werk.</figcaption></figure>



<p class="justify-text">Beschouw nu Fig. 2: het verschil met de vorige tekening is niet groot: we zien nu dat het EDA subsysteem wordt opgeroepen tijdens het uitvoeren van het normale werk als gevolg van het binnenkomende commando. Wanneer het Event is gepubliceerd én het andere werk is uitgevoerd, kan de transactie worden afgewerkt. Publicatie van het Event betekent dat we bevestiging hebben gekregen van de Event Broker dat het goed door deze is ontvangen, maar uiteraard niet noodzakelijk reeds naar de subscribers is gestuurd. Dit is net één van de voordelen van de asynchrone communicatie binnen EDA.</p>



<p class="justify-text">Bij deze fase moeten we er wel op letten dat we op een zeer betrouwbare Event Broker kunnen rekenen. Vermits deze online moet zijn om het Event in ontvangst te nemen tíjdens de transactie, zou de transactie worden geblokkeerd indien er daarbij een fout optreedt. Men zou dit als een nadeel kunnen beschouwen, maar we moeten er aan denken dat het Event kan worden gebruikt als plaatsvervanger van het eventuele rechtstreeks oproepen van alle subscribers, indien deze tijdig op de hoogte moeten worden gebracht van wat er wordt beoogd met het uitvoeren van de transactie. Indien men tijdens het verwerken van het commando normaal gezien beroep deed op achterliggende APIs van andere systemen, kan men deze andere systemen nu in plaats daarvan inschrijven op het Event, waardoor deze API calls niet meer hoeven gebeuren en onze toepassing dus niet langer afhankelijk is van de achterliggende. Op deze manier vermínderen we de kans op falen van de transactie indien de Event Broker betrouwbaarder wordt gemaakt dan de andere achterliggende systemen.</p>



<h2 class="wp-block-heading">Fase 3: Event-First Programming, Transactioneel</h2>



<p class="justify-text">Tot nu toe waren onze wijzigingen in de oorspronkelijke toepassing vrij conservatief: het doel was een reeds bestaand systeem Events te laten publiceren ten voordele van het grotere ecosysteem (we zagen daarbij dat dit in principe kan leiden tot het verminderen van het gebruik van APIs van andere systemen en op die manier tot minder afhankelijkheden).</p>



<p class="justify-text">Vanaf fase 3 zullen we echter ook de eigen toepassing gebruik laten maken van de eigen Events, alvorens, als gevolg van het ontvangen van deze Events, het normale werk te doen. Dit noem ik Event-First programming, en het laat toe om een standaard stramien te hebben om te reageren op binnenkomende informatie: alle belangrijke wijzigingen komen nu binnen via Events. Dat betekent dat we op dezelfde manier zullen reageren op de eigen Events, als op andere Events van het ecosysteem, komende van andere toepassingen.</p>



<figure class="wp-block-image aligncenter size-large"><a href="/wp-content/uploads/2023/12/fase3.png"><img loading="lazy" decoding="async" width="1024" height="450" src="/wp-content/uploads/2023/12/fase3-1024x450.png" alt="" class="wp-image-19621" srcset="https://www.smalsresearch.be/wp-content/uploads/2023/12/fase3-1024x450.png 1024w, https://www.smalsresearch.be/wp-content/uploads/2023/12/fase3-300x132.png 300w, https://www.smalsresearch.be/wp-content/uploads/2023/12/fase3-768x338.png 768w, https://www.smalsresearch.be/wp-content/uploads/2023/12/fase3.png 1173w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a><figcaption class="wp-element-caption">Figuur 3: Event-First programmeren, met kunstmatig behoud van de volledig transactie.</figcaption></figure>



<p class="justify-text">Beschouw Fig. 3: om de transactie (voor het commando) op te volgen, voeren we een extra controller in. Als eerste stap wordt er nu een Event gepubliceerd als gevolg van het binnenkomende commando. Het EDA subsysteem zal dit Event publiceren, en óók de applicatie zelf (naast eventuele andere in het ecosysteem), zullen er zich voor inschrijven. Wanneer het Event dan opnieuw binnenkomt in de applicatie ten gevolge van de subscription, wordt het effectieve werk uitgevoerd dat de applicatie moet doen ten gevolge van het commando. Om de transactie, ten slotte, te kunnen beëindigen, moet de controller worden ingelicht wanneer het werk is gedaan. Hier zijn we vrij om dit opnieuw via een Event te doen, of op een andere manier (gebruik makend van een of ander bestaand mechanisme voor communicatie tussen threads dat wordt aangeboden door de programmeertaal).</p>



<p class="justify-text">Indien we deze fase voor een toepassing volledig implementeren (i.e. toepassen op álle binnenkomende commando&#8217;s), kunnen we de toepassing verder gaan modulariseren volgens het principe van CQRS (<a href="/architecturale-evoluties-deel-2/" data-type="post" data-id="11475">Command &amp; Query Responsability Segregation</a>). Dit wil zeggen dat modules die reageren op commando&#8217;s apart zullen staan van modules die reageren op queries.</p>



<p class="justify-text">Als u heeft opgemerkt dat het een beetje raar is dat we via een extra controller gaan wachten op een bericht dat het werk, als gevolg van ons Event, is gedaan en we onze transactie nu kunnen beëindigen, dan heeft u gelijk: we hebben deze fase eerder als illustratie ingevoegd om het contrast met de volgende fase te verduidelijken. Maar het lijkt ons eerder aangeraden om fase 3 over te slaan en onmiddellijk gebruik te maken van Eventual Consistency!</p>



<h2 class="wp-block-heading">Fase 4: Eventual Consistency</h2>



<p class="justify-text">Tot nu toe hielden we sterk vast aan de transactionaliteit van het uitvoeren van ons binnenkomende commando. Eigenlijk is dit een kunstmatig opgelegde beperking, die ons ervan weerhoudt maximaal in te zetten op de availability van het ecosysteem (zie: <a href="/newsql-een-upgrade-voor-je-oude-database/" data-type="post" data-id="13610">CAP theorema</a>). In fase 4 zullen we gaan vertrouwen in het concept <a href="/eventual-consistency-1/" data-type="post" data-id="15544">Eventual Consistency</a>: we gaan het commando als uitgevoerd beschouwen, van zodra we zeker zijn dat ons Event is gepubliceerd. We gaan er dan van uit dat de toestand van de applicatie (en, per extensie, van het volledige ecosysteem), na verloop van tijd (&#8220;eventually&#8221;) consistent zal worden en alle nodige zaken zijn gebeurd als gevolg van het commando (ook in andere toepassingen!). Typisch zal deze tijd redelijk kort zijn; we laten enkel de mogelijkheid open dat het langer kan duren, omdat we het falen van een achterliggend systeem nu kunnen toelaten (zie ook het <a href="/newsql-getest-en-goedgekeurd/" data-type="post" data-id="13705">PACELC theorema</a>).</p>



<figure class="wp-block-image aligncenter size-large"><a href="/wp-content/uploads/2023/12/fase4.png"><img loading="lazy" decoding="async" width="1024" height="445" src="/wp-content/uploads/2023/12/fase4-1024x445.png" alt="" class="wp-image-19623" srcset="https://www.smalsresearch.be/wp-content/uploads/2023/12/fase4-1024x445.png 1024w, https://www.smalsresearch.be/wp-content/uploads/2023/12/fase4-300x130.png 300w, https://www.smalsresearch.be/wp-content/uploads/2023/12/fase4-768x334.png 768w, https://www.smalsresearch.be/wp-content/uploads/2023/12/fase4.png 1187w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></a><figcaption class="wp-element-caption">Figuur 4: Event-First programmeren, met Eventual Consistency</figcaption></figure>



<p class="justify-text">Beschouw nu Fig. 4: eigenlijk doen we hier hetzelfde als in Fig. 3, maar dan met een vereenvoudiging: er hoeft geen feedback meer te komen van &#8220;Internal Work&#8221; naar de &#8220;Controller&#8221; voor het commando. Deze laatste zal nu simpelweg het commando als uitgevoerd beschouwen wanneer het Event is verstuurd (we hadden de extra controller eigenlijk terug weg kunnen laten). Met deze manier van werken verkrijgen we het meeste voordeel uit EDA voor de eigen applicatie (het voordeel voor het ecosysteem kregen we reeds in fase 1).</p>



<h2 class="wp-block-heading">Besluit</h2>



<p class="justify-text">In deze blog-post lieten we een mogelijke, stapsgewijze evolutie zien van een computerprogramma dat bij het uitvoeren van een commando een business Event zou moeten publiceren. In de eerste fases wordt de impact geminimaliseerd; in latere fases wordt de toepassing zelf meer Event Driven gemaakt. Het spreekt voor zich dat deze manier van werken niet de enige goede is, en dat men ook niet steeds álle stappen hoeft te zetten.</p>



<p class="justify-text">We beseffen dat de vier fases zeer verboos zijn gedocumenteerd in dit schrijven; voor programmeurs kan dit nogal overbodig lijken. Maar we richten deze blog ook op niet-programmeurs, zodat voor hen een tipje van de sluier wordt gelicht over hoe programmeurs moeten nadenken over het echte binnenwerk van een toepassing, en hoe dit in verband staat met de communicatie op schaal van het ecosysteem waarbinnen een toepassing opereert.</p>



<p class="justify-text">Het publiceren van herbruikbare business Events is cruciaal voor een groot IT ecosysteem, waarbij integraties, <a href="/event-driven-apis/" data-type="post" data-id="16655">louter op basis van APIs</a>, op langere termijn voor een verminderde resiliëntie en agility kunnen zorgen. Een goed evenwicht tussen integraties via zowel synchrone als asynchrone communicatie, waarbij EDA als evenwaardig wordt beschouwd aan API, leidt tot het meest gezonde ecosysteem van applicaties.</p>





<p></p>
]]></content:encoded>
					
					<wfw:commentRss>https://www.smalsresearch.be/meer-eda-stap-voor-stap-programmeren/feed/</wfw:commentRss>
			<slash:comments>3</slash:comments>
		
		
			</item>
		<item>
		<title>Ecosysteem Architectuur</title>
		<link>https://www.smalsresearch.be/ecosysteem-architectuur/</link>
		
		<dc:creator><![CDATA[Koen Vanderkimpen]]></dc:creator>
		<pubDate>Mon, 28 Feb 2022 16:22:49 +0000</pubDate>
				<category><![CDATA[[NL]]]></category>
		<category><![CDATA[Blog post]]></category>
		<category><![CDATA[API]]></category>
		<category><![CDATA[architecture]]></category>
		<category><![CDATA[cloud computing]]></category>
		<category><![CDATA[CQRS]]></category>
		<category><![CDATA[EDA]]></category>
		<category><![CDATA[Event]]></category>
		<category><![CDATA[Eventual Consistency]]></category>
		<category><![CDATA[mesh]]></category>
		<category><![CDATA[methodology]]></category>
		<category><![CDATA[microservices]]></category>
		<category><![CDATA[NewSQL]]></category>
		<category><![CDATA[rest]]></category>
		<category><![CDATA[Software architectures]]></category>
		<category><![CDATA[software design]]></category>
		<category><![CDATA[software engineering]]></category>
		<guid isPermaLink="false">/?p=16980</guid>

					<description><![CDATA[Bij het software bouwen, maken we meestal geen op zichzelf staande programma&#8217;s meer. We bouwen vandaag eerder Applicatie Ecosystemen. Wanneer we dus een stuk software schrijven, mogen we niet zomaar de ontwikkeling lokaal optimaliseren, maar moeten we ook continu rekening houden met het grotere geheel. In deze blog maken we een verkenning van een aantal [&#8230;]]]></description>
										<content:encoded><![CDATA[
<div class="wp-block-image"><figure class="alignleft size-full is-resized"><a href="/wp-content/uploads/2016/06/logomicro.png"><img loading="lazy" decoding="async" src="/wp-content/uploads/2016/06/logomicro.png" alt="" class="wp-image-9733" width="163" height="147" srcset="https://www.smalsresearch.be/wp-content/uploads/2016/06/logomicro.png 679w, https://www.smalsresearch.be/wp-content/uploads/2016/06/logomicro-300x272.png 300w" sizes="auto, (max-width: 163px) 100vw, 163px" /></a></figure></div>



<p class="justify-text">Bij het software bouwen, maken we meestal geen op zichzelf staande programma&#8217;s meer. We bouwen vandaag eerder Applicatie Ecosystemen. Wanneer we dus een stuk software schrijven, mogen we niet zomaar de ontwikkeling lokaal optimaliseren, maar moeten we ook continu rekening houden met het grotere geheel. In deze blog maken we een verkenning van een aantal zaken waar we rekening mee moeten houden bij het bouwen van een ecosysteem, en van concrete principes die we kunnen toepassen bij het uitbouwen van een erbij passende modulaire architectuur.</p>



<span id="more-16980"></span>



<h2 class="wp-block-heading" id="de-paradox-van-de-afhankelijkheid">De Paradox van de Afhankelijkheid</h2>



<p class="justify-text">Er heerst grote waarde in zaken met elkaar verbinden, en in reeds bestaande zaken te <a href="/hergebruik-de-dos-en-donts/" data-type="post" data-id="13002">hergebruiken</a> bij het bouwen van nieuwe dingen. Gegevens, en ook de manier waarop ze worden verwerkt, ja, soms zelfs hele stukken van een applicatie, van één instelling, kunnen ook van pas komen bij een andere. En uiteraard geldt hetzelfde ook al binnen één en dezelfde instelling. Er is dus een meerwaarde te vinden door zaken met elkaar te verbinden en door zaken van elkaar te gaan hergebruiken. Dit is ook het hele opzet achter het <a href="https://www.ict-reuse.be/nl">ReUse verhaal binnen onze sector</a>. Connecties en communicaties tussen systemen creëren hergebruik, efficiëntie en business waarde.</p>



<p class="justify-text">Maar wanneer we zaken verbinden, maken we ze van elkaar afhankelijk. Die afhankelijkheid heeft op technisch vlak vooral nadelen. Denk maar aan het onbeschikbaar zijn van een dienst waarvan andere diensten rechtstreeks afhangen; vaak worden deze laatste dan eveneens <a href="/99-9-availability-fundamenteel-anders/" data-type="post" data-id="1244">onbeschikbaar</a>. Maar ook semantisch maakt het de zaken moeilijker. We mogen niet zomaar puur lokaal nadenken over alle concepten die we in onze computerprogramma&#8217;s verwerken; nee, we moeten er rekening mee houden dat ze geïntegreerd of hergebruikt kunnen worden. We moeten ervoor proberen te zorgen dat de betekenis ervan voorbijgaat aan wat puur noodzakelijk is voor ons specifieke geval. Dat soort zaken maakt het ontwikkelen van software een stuk moeilijker. Dit niet doen is echter nog erger: de &#8220;technical debt&#8221; die ontstaat door teveel kortetermijn- en lokaal denken, zal dan op termijn alleen maar onbeheersbaarder worden.</p>



<p class="justify-text">En dat is dus de paradox: de afhankelijkheid tussen de systemen binnen een applicatie ecosysteem creëert enorme business waarde, maar maakt de IT een stuk lastiger (en duurder).</p>



<h2 class="wp-block-heading" id="de-mesh-van-microservices">De &#8220;Mesh&#8221; Architectuur</h2>



<p class="justify-text">Een goede architectuur kan echter soelaas brengen in dit verhaal, en consequent rekening houden met hergebruik kan uiteindelijk zelfs geld gaan besparen. Het gebruik van een <a href="/services-in-alle-maten-van-macro-naar-nano/" data-type="post" data-id="11111">Service Oriented Architecture (SOA)</a> is daarbij één van onze belangrijkste wapens om de afhankelijkheden in ons ecosysteem de baas te kunnen, met de <a href="/van-n-tier-naar-microservices/" data-type="post" data-id="9702">Microservices Architectuur</a> als ultieme voorbeeld. Dit zijn echter slechts voorbeeld technische implementaties van het belangrijke concept <em>Modulariteit </em>(dat men in principe zelfs binnenin een monolithisch systeem kan implementeren). Wat proberen we hiermee te bereiken?</p>



<ul class="justify-text wp-block-list"><li>Modules zijn zo onafhankelijk van elkaar als maar kan (maar maken toch van elkaar gebruik vanwege de waarde die dit heeft): ze zijn liefst &#8220;loosely coupled&#8221;: veranderingen in de werking of het ontwerp van één module hebben zo weinig mogelijk impact op de werking of het ontwerp van een andere. Dit laat toe om ze apart van elkaar te laten werken en ze te laten onderhouden door aparte teams, zonder dat er continu overleg of downtime moet zijn (in het geval van een monoliet verliest men wel dit downtime voordeel).</li><li>Modules zijn voldoende klein. Men volgt hier de <a href="https://en.wikipedia.org/wiki/Unix_philosophy">Unix filosofie &#8220;do one thing and do it well&#8221;</a>. In de praktijk wil dit zeggen dat modules gericht zijn op het aanbieden van één bepaalde business capabiliteit, die in principe apart kan worden gedeployed. Hoe men precies de context van een service afbakent, is één van de belangrijkste onderdelen van de <a href="https://en.wikipedia.org/wiki/Domain-driven_design">Domain Driven Design (DDD)</a> ontwikkelingsmethode.</li></ul>



<p class="justify-text">Het tweede punt is niet te onderschatten en één van de moeilijkste zaken, reeds bij de business en functionele analyse en ook verderop in het ontwerp van software. In deze blog richten we ons echter op de aspecten van een groter ecosysteem, en daarom zullen we ons hier beperken tot de eerste vraag: </p>



<blockquote class="wp-block-quote has-text-align-center is-layout-flow wp-block-quote-is-layout-flow"><p>Hoe houden we onze modules zo goed mogelijk onafhankelijk, terwijl we ze toch laten communiceren?</p></blockquote>



<h2 class="wp-block-heading" id="een-aantal-helpende-principes">Een aantal helpende Principes</h2>



<p class="justify-text">We gaan er vanaf hier van uit dat we onze modules verpakken in aparte services, en we zullen nu een aantal ontwerpprincipes overlopen die ons gaan helpen bij het uitbouwen van een ecosysteem architectuur waarin we een grote onafhankelijkheid, maar ook herbruikbaarheid, van onze services nastreven.</p>



<div class="wp-block-image justify-text"><figure class="alignright size-full is-resized"><a href="/wp-content/uploads/2022/02/usingAPI.png"><img loading="lazy" decoding="async" src="/wp-content/uploads/2022/02/usingAPI.png" alt="" class="wp-image-17010" width="309" height="172" srcset="https://www.smalsresearch.be/wp-content/uploads/2022/02/usingAPI.png 497w, https://www.smalsresearch.be/wp-content/uploads/2022/02/usingAPI-300x167.png 300w" sizes="auto, (max-width: 309px) 100vw, 309px" /></a><figcaption>Figuur 1: Twee APIs, telkens geïmplementeerd door een onderliggende service. De ene service gebruikt de API van de andere, en is dus enkel daarvan afhankelijk en niet van de onderliggende service. De pijl duidt hier de richting van de afhankelijkheid aan, maar de communicatie is steeds bidirectioneel (vraag-antwoord) en synchroon (men wacht op het antwoord).</figcaption></figure></div>



<p class="justify-text"><strong>1.  Het gebruik van APIs</strong>. Dit principe is reeds goed gekend en vormt een basissteen van SOA: Een <a href="/data-centric-it-met-rest/" data-type="post" data-id="9535">service stelt zich open naar de buitenwereld toe via zijn API</a>, en deze API is dan ook het enige waarvan andere services afhankelijk kunnen zijn. Op die manier beperkt men dus de afhankelijkheid die andere zaken m.b.t. een service zullen hebben, tot wat strikt noodzakelijk is. Men is hier echter wel nog semantisch en syntactisch afhankelijk van de APIs van andere services die men wenst te gebruiken, en ook technisch afhankelijk van het online zijn van die andere services.</p>



<p class="justify-text"><strong>2.  Het gebruik van Events</strong>. <a href="/event-driven-apis/" data-type="post" data-id="16655">Event Driven Architecture</a> is ook al oud, maar maakt meer recent furore dankzij de Reactive beweging. In plaats van (of naast) communicatie via een API, kan men de communicatie tussen services ook via het versturen van <a href="/het-event-als-leidend-voorwerp-in-software-engineering/" data-type="post" data-id="8942">events</a> laten gebeuren. Daar hoort bij dat een service die een event verstuurt, niet op voorhand weet welke andere services dit event zullen ontvangen. Services hebben hier enkel controle over de events die ze zelf versturen en dewelke ze zelf wensen te ontvangen. Het is duidelijk dat hier de onafhankelijkheid nog sterker is dan in het geval van APIs: men is niet langer rechtstreeks afhankelijk van de interface, noch van het online zijn, van een andere service. Men is enkel nog technisch afhankelijk van het online zijn van de <a href="/geavanceerd-event-driven-engineering/">Event Bus</a> (een middleware systeem dat men met grote redundantie kan opzetten), en semantisch afhankelijk van de definitie van de betrokken events (een niet te vermijden afhankelijkheid die wordt opgelegd door de business vereiste van het gebruik van de betreffende business capabiliteit die door het event mede wordt ondersteund).</p>



<div class="wp-block-image justify-text"><figure class="alignleft size-full is-resized"><a href="/wp-content/uploads/2022/02/usingCQRS-Events.png"><img loading="lazy" decoding="async" src="/wp-content/uploads/2022/02/usingCQRS-Events.png" alt="" class="wp-image-17035" width="302" height="285" srcset="https://www.smalsresearch.be/wp-content/uploads/2022/02/usingCQRS-Events.png 467w, https://www.smalsresearch.be/wp-content/uploads/2022/02/usingCQRS-Events-300x283.png 300w" sizes="auto, (max-width: 302px) 100vw, 302px" /></a><figcaption>Figuur 2: Twee services die gebruik maken van events om met elkaar te communiceren. De eerste biedt een command API aan, dewelke door een client wordt gebruikt om data in te dienen. Daarna stuurt deze een event naar de Event Bus, dat iets later ontvangen wordt door de tweede service. Deze zal het event gebruiken om zijn opvraagbare data te updaten, zodat deze daarna door een client kan worden opgevraagd. De pijlen van de events duiden effectief op éénrichtingscommunicatie, waarbij men niet wacht op antwoord (asynchroon).</figcaption></figure></div>



<p class="justify-text"><strong>3.  CQRS</strong>. Wanneer we microservices bouwen die zo klein en onafhankelijk mogelijk zijn, betekent dit eigenlijk dat we een onderscheid moeten beginnen maken tussen services die data binnenkrijgen en/of (deels) verwerken, en services die daarop verder bouwen om informatie te verschaffen en vragen te kunnen beantwoorden. Typisch zullen dit verschillende business capabilities zijn, en dus een aparte service vereisen. Bovendien maken we de microservices liefst zo klein, dat er vaak data van meerdere microservices afkomstig, nodig zal zijn om bepaalde queries te beantwoorden, waardoor het sowieso minder vanzelfsprekend wordt om de queries te implementeren als onderdeel van één van die microservices; ook daardoor wordt het dus logischer om ze in een aparte dienst te deployen. Dit principe noemen we <a href="https://martinfowler.com/bliki/CQRS.html">Command Query Responsability Segregation (CQRS)</a>: we scheiden de ver-antwoordelijkheid voor het behandelen van commando&#8217;s (opnemen en verwerken van data) en die voor het beantwoorden van queries (teruggeven van, meestal verwerkte, data) in aparte services.</p>



<p class="justify-text"><strong>4.  Sagas</strong>. Soms is het nodig dat in een applicatie zaken gebeuren die ofwel gezamenlijk slagen, ofwel gezamenlijk falen. Dit noemt men een transactie. Zoals reeds in een <a href="/eventual-consistency-1/" data-type="post" data-id="15544">eerdere blog</a> vermeld, is het nuttig om transacties binnen onze systemen te minimaliseren en goed na te denken op business niveau of ze echt wel nodig zijn. Desalniettemin zullen we ze toch niet geheel kunnen vermijden. Binnen één microservice is de implementatie hiervan doorgaans geen probleem: de onderliggende database zal dit ondersteunen volgens het tweefasig &#8220;commit&#8221; protocol (2 Phase Commit, 2PC). Wat we echter absoluut moeten vermijden, is om dit protocol toe te passen op meerdere services tegelijk <a href="/high-availability-wc-papier/" data-type="post" data-id="1368">in een gedistribueerde omgeving</a>. Om dan toch tegemoet te komen aan de nood aan gedistribueerde transacties, kunnen we sagas gebruiken. Een saga bestaat uit een reeks lokale transacties (binnen één service), waarbij elke service een event zal publiceren om de volgende transactie binnen de saga te triggeren in de volgende service die eraan meedoet. Indien één van de lokale transacties faalt, dan zal het verstuurde event verschillen van wat het normaal is, en dan volgen compenserende transacties in de services die reeds aan beurt kwamen, om de eerdere veranderingen terug ongedaan te maken. Men kan sagas op 2 manieren implementeren: de eerste is een <em>choreografie</em>, waarbij de services zelf weten wat ze wanneer moeten doen (op basis van de events die ze binnenkrijgen). De tweede optie is de <em>orchestratie</em>, waarbij één service zal optreden als de organisator van het gebeuren en de transactie stap voor stap opvolgt. De communicatie met participerende services kan hier ook met events plaatsvinden, maar eventueel ook via rechtstreekse API calls om de opeenvolgende opdrachten te geven (de antwoorden komen dan wel best via events terug binnen in de orchestrator, anders zondigt men tegen CQRS). Een voorbeeld van een saga (met choreografie) is het verhaal van de webshop in de <a href="/event-driven-apis/" data-type="post" data-id="16655">vorige blog over Event-Driven APIs</a>.</p>



<p class="justify-text">Naast deze 4 principes zijn er nog een aantal secundaire ondersteunende zaken die we mogelijk kunnen doen binnen ons ecosysteem. Denk bijvoorbeeld aan het gebruik van <a href="/geavanceerd-event-driven-engineering/" data-type="post" data-id="9041">Event Sourcing</a>, of het inzetten van <a href="/newsql-getest-en-goedgekeurd/" data-type="post" data-id="13705">NewSQL databases</a> om een microservice met toestand goed te kunnen schalen. Deze zaken bespraken we reeds voldoende in vorige blogposts.</p>



<h2 class="wp-block-heading" id="besluit-even-wennen">Besluit: even Wennen</h2>



<p class="justify-text">Een moderne architectuur voor een complex Applicatie Ecosysteem bestaat uit meer dan alleen maar APIs, en kan best stevig gebruik maken van de toegevoegde waarde die EDA en CQRS bieden. Wanneer men eerder traditionele architecturen gewend is, is de verhoogde complexiteit natuurlijk even wennen. De voordelen overwegen volgens ons echter op de nadelen van deze leercurve. Eens men deze zaken in de vingers heeft en een aantal keer heeft toegepast, zal men zowel op technisch vlak als op business vlak de pluspunten beginnen ondervinden.</p>



<p class="justify-text">Om het allemaal een beetje behapbaarder te maken, zullen we in een volgende blog trachten deze principes verder te illustreren aan de hand van een voorbeeld applicatie ecosysteem.</p>





<p></p>



<p></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Voorbij aan REST: Event-Driven APIs</title>
		<link>https://www.smalsresearch.be/event-driven-apis/</link>
		
		<dc:creator><![CDATA[Koen Vanderkimpen]]></dc:creator>
		<pubDate>Tue, 30 Nov 2021 10:23:22 +0000</pubDate>
				<category><![CDATA[[NL]]]></category>
		<category><![CDATA[Blog post]]></category>
		<category><![CDATA[API]]></category>
		<category><![CDATA[cloud computing]]></category>
		<category><![CDATA[CQRS]]></category>
		<category><![CDATA[EDA]]></category>
		<category><![CDATA[Event]]></category>
		<category><![CDATA[Eventual Consistency]]></category>
		<category><![CDATA[methodology]]></category>
		<category><![CDATA[reactive]]></category>
		<category><![CDATA[Resilience]]></category>
		<category><![CDATA[rest]]></category>
		<category><![CDATA[Software architectures]]></category>
		<category><![CDATA[software engineering]]></category>
		<category><![CDATA[standards]]></category>
		<category><![CDATA[vortex]]></category>
		<guid isPermaLink="false">/?p=16655</guid>

					<description><![CDATA[We hadden het op deze blog reeds uitvoerig over het gebruik van APIs als bouwsteen voor herbruikbare software. RESTful APIs hebben uiteraard heel wat voordelen, maar toch moeten we opletten dat we ze niet altijd en overal gaan inzetten. Er zijn namelijk ook nadelen verbonden aan deze manier van werken. Met deze blog willen we [&#8230;]]]></description>
										<content:encoded><![CDATA[
<div class="wp-block-image"><figure class="alignleft size-full is-resized"><a href="/wp-content/uploads/2021/11/EventAPI-1.png"><img loading="lazy" decoding="async" src="/wp-content/uploads/2021/11/EventAPI-1.png" alt="" class="wp-image-16720" width="179" height="179" srcset="https://www.smalsresearch.be/wp-content/uploads/2021/11/EventAPI-1.png 240w, https://www.smalsresearch.be/wp-content/uploads/2021/11/EventAPI-1-150x150.png 150w" sizes="auto, (max-width: 179px) 100vw, 179px" /></a></figure></div>



<p class="justify-text">We hadden het op deze blog reeds uitvoerig over het gebruik van <a href="/the_api_event/" data-type="post" data-id="15137">APIs als bouwsteen</a> voor <a href="/hergebruik-de-dos-en-donts/" data-type="post" data-id="13002">herbruikbare software</a>. <a href="/data-centric-it-met-rest/" data-type="post" data-id="9535">RESTful APIs</a> hebben uiteraard heel wat voordelen, maar toch moeten we opletten dat we ze niet altijd en overal gaan inzetten. Er zijn namelijk ook nadelen verbonden aan deze manier van werken. Met deze blog willen we er op wijzen dat asynchrone, <a href="/het-event-als-leidend-voorwerp-in-software-engineering/" data-type="post" data-id="8942">Event-Driven communicatie</a> tussen de systemen soms een veel beter resultaat oplevert, dan het zuivere gebruik van RESTful APIs.</p>



<span id="more-16655"></span>



<h2 class="wp-block-heading">REST: de gouden standaard</h2>



<p class="justify-text">We hebben er zelf reeds enkele malen op gehamerd: <a href="/groei-van-rest-json-standaarden-voor-identity-management/" data-type="post" data-id="2327">RESTful APIs zijn al jaren de de facto standaard</a> voor de communicatie tussen services en hebben ons tal van voordelen gebracht. Zo maken ze het b.v. eenvoudig om diensten te kunnen ontwikkelen op een technologie-agnostische manier, zolang de API maar goed gestandaardiseerd is. Een REST API geeft je ook rechtstreekse controle over wat een service voor jou doet en laat toe om <a href="/newsql-een-upgrade-voor-je-oude-database/" data-type="post" data-id="13610">gedistribueerde transacties</a> uit te voeren.</p>



<p class="justify-text">Het belangrijkste voordeel van REST is dat de technologie heel goed ingeburgerd en breed geaccepteerd is. Het is daardoor makkelijk om ontwikkelaars te vinden die ermee om kunnen gaan. Ondertussen zijn er ook tal van goede raamwerken rond gebouwd en ook standaarden voor de definitie en omschrijving van APIs, waardoor RESTful APIs de ultieme <a href="/hergebruik-de-dos-en-donts/" data-type="post" data-id="13002">bouwstenen van herbruikbaarheid</a> zijn geworden.</p>



<p class="justify-text">Het gevaar is echter dat RESTful APIs zó nuttig zijn, dat ze als een gouden hamer gaan worden gebruikt: deze RESTful hamer werkt zo goed, dat elk project en elk probleem als een spijker wordt beschouwd. Kortom, de technologie wordt steevast toegepast, daar waar soms andere keuzes een betere oplossing kunnen vormen. Er zijn namelijk een aantal nadelen verbonden aan een aanpak enkel en alleen gebaseerd op APIs&#8230;</p>



<h2 class="wp-block-heading">De pure API aanpak</h2>



<p class="justify-text">Wanneer we tegenwoordig <a href="/architecturale-evoluties-deel-1/" data-type="post" data-id="11434">software ontwikkelen</a>, zullen we dit niet meer monolitihisch doen. Om de beschikbaarheid te verhogen en om elastisch schaalbare diensten te bouwen, zullen we de functionaliteit zo goed mogelijk verdelen over een aantal <a href="/van-n-tier-naar-microservices/" data-type="post" data-id="9702">zo klein mogelijke services, mogelijks zelfs microservices</a>. Deze zullen dan samen, onderling communicerend, alle functionaliteit voor een applicatie, of meerdere applicaties, implementeren. Bij een enigszins naïeve aanpak zal men al deze communicatie eenvoudigweg voorzien d.m.v. het gebruik van RESTful APIs, en zal elke dienst de andere diensten synchroon oproepen wanneer deze de functionaliteit ervan nodig heeft.</p>



<p class="justify-text">Voor alle duidelijkheid: een synchrone oproep is een oproep die onmiddellijk antwoord verwacht van de tegenpartij. Een asynchroon bericht is éénrichtingsverkeer (al kan er &#8211; later &#8211; wel een antwoord komen in de vorm van een ander asynchroon bericht; het verschil is dat de eerste partij niet wacht op een antwoord en gewoon zijn werk verder zet).</p>



<div class="wp-block-image"><figure class="aligncenter size-full"><a href="/wp-content/uploads/2021/11/PureApi-1.png"><img loading="lazy" decoding="async" width="703" height="368" src="/wp-content/uploads/2021/11/PureApi-1.png" alt="" class="wp-image-16673" srcset="https://www.smalsresearch.be/wp-content/uploads/2021/11/PureApi-1.png 703w, https://www.smalsresearch.be/wp-content/uploads/2021/11/PureApi-1-300x157.png 300w" sizes="auto, (max-width: 703px) 100vw, 703px" /></a><figcaption>Figuur 1: De Webstore, met enkel synchrone communicatie (via APIs) tussen microservices.</figcaption></figure></div>



<p class="justify-text">Laten we het voorbeeld in Figuur 1 bespreken: Het betreft een webwinkel, opgebouwd via een microservices aanpak, waarbij alle microservices met elkaar communiceren via hun APIs. In de figuur staan 14 point-to-point afhankelijkheden; we zullen deze overlopen aan de hand van een typisch scenario. </p>



<ol class="justify-text wp-block-list"><li>De gebruiker logt in (REST call van Webstore Site naar Customer voor de gebruikersgegevens)</li><li>Customer doet ook een call naar Cart om een eerder opgeslagen winkelkarretje in te laden</li><li>De gebruiker winkelt: calls naar Catalog (query) en calls naar Cart (update)</li><li>Op zijn beurt zal Catalog de Inventory service aanroepen om te zien wat voorradig is</li><li>De gebruiker wil afrekenen: call van Site naar Checkout</li><li>Checkout roept Customer en Cart op, om de adresgegevens van de klant in te laden en de inhoud van het karretje</li><li>Call van Checkout naar Shipping voor de verzendingskost</li><li>Achter de schermen roept Shipping hiertoe mogelijks een externe API op van de koerier</li><li>De betaling wordt gestart: call van Checkout naar Payment</li><li>Payment roept Customer op voor de opgeslagen betalingsgegevens</li><li>Na de betaling werkt de Checkout module het order af met een Call naar Shipping en naar Inventory</li><li>Ook Orders krijgt een call om het afgewerkte order op te slaan</li><li>De klant kijkt zijn bestellingen nog eens na: call van Customer naar Orders</li></ol>



<p class="justify-text">Zoals we kunnen zien heeft de microservices approach al een<a href="/architecturale-evoluties-deel-2/" data-type="post" data-id="11475"> voordeel tegenover de monolithische aanpak</a>: er mogen een paar services plat zijn, en mensen kunnen toch winkelen (zonder in te loggen zijn enkel cart, catalog en eventueel inventory nodig). Enkel tijdens een checkout zijn zowat alle services nodig (behalve de catalog).</p>



<p class="justify-text">Dit laatste blijft natuurlijk een probleem: door de vele onderlinge afhankelijkheden tussen de services, kunnen er cascades ontstaan: de onbeschikbaarheid van één service kan de werking van vele andere verstoren en zelfs verhinderen. Daarnaast moet men met al deze afhankelijkheden rekening houden wanneer men een nieuwe versie van een service wil bouwen. Verder is het ook zo dat we van alles impliciet een transactie maken (en als één stap faalt, faalt de hele transactie), terwijl dit misschien niet noodzakelijk is op business niveau. Dit transactionele aspect verplicht ons ook om telkens alle stappen opnieuw te doorlopen in geval van een fout, en kan er, indien er zaken weggeschreven worden tijdens de transactie, ook voor zorgen dat we zaken terug actief ongedaan moeten maken indien er een fout is opgetreden, om te vermijden dat de achterliggende <a href="/data-quality-anomalies-transactions-management-system-atms-prototype-work-in-progress/" data-type="post" data-id="14866">data corrupt wordt</a>.</p>



<p class="justify-text">De directe koppeling tussen de vele diensten heeft nog een ander gevolg: de onafhankelijkheid van de microservices komt in het gedrang. Het hoofddoel van een microservices aanpak, is dat men een collectie onafhankelijk opererende diensten verkrijgt, die afzonderlijk van elkaar kunnen opereren en evolueren. Hoe sterker ze echter gekoppeld zijn aan elkaar, hoe minder groot deze onafhankelijkheid wordt.</p>



<h2 class="wp-block-heading">Richting asynchrone communicatie</h2>



<p class="justify-text">We hebben reeds in vorige blogs besproken wat <a href="/geavanceerd-event-driven-engineering/" data-type="post" data-id="9041">Event-Driven Architecture (EDA) is en welke geavanceerde toepassingen er bestaan</a>, gebaseerd op dat paradigma. Kort herhaald, gaat het hier over asynchrone communicatie tussen toepassingen, doordat ze events publiceren en zich op events van andere systemen kunnen abonneren. Dit zorgt voor een extra indirectie tussen de toepassingen, en op die manier kunnen ze onafhankelijker van elkaar opereren. Een EDA systeem is ook erg uitbreidbaar: je kan altijd extra services toevoegen aan het geheel, die reeds bestaande events gaan gebruiken om nieuwe functionaliteit te implementeren, en die op hun beurt nieuwe events kunnen publiceren. <a href="/architecturale-evoluties-deel-2/" data-type="post" data-id="11475" target="_blank" rel="noreferrer noopener">Op die manier krijg je een groeiend ecosysteem van nuttige Events, net zoals je ook met APIs een ecosysteem kan ontwikkelen</a>.</p>



<p class="justify-text">De wereld heeft echter niet stilgestaan sinds onze vorige posts over EDA en ondertussen zijn er op technologisch vlak al heel wat interessante evoluties bijgekomen. Het is nu zelfs vrij gemakkelijk geworden om ook de front-ends van applicaties aan te sluiten op een Event-Driven omgeving. Je kan je natuurlijk gaan afvragen of er ondertussen ook nog geen standaarden bestaan voor EDA, op basis waarvan we herbruikbare zaken kunnen gaan ontwikkelen, en die zijn er ook stilaan. Het voornaamste wat we kunnen doen om EDA goed te kunnen gebruiken, is echter eerst en vooral ze als &#8220;first class citizen&#8221; gaan beschouwen vanaf de business analyse, en niet langer als een louter technische vernuftigheid die een aantal problemen in systemen kan oplossen.</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow"><p>Beschouw Events als First Class Citizen: neem ze mee in je visie en vanaf de business analyse.</p></blockquote>



<p class="justify-text">De meeste business domeinen zijn intrinsiek Event-gebaseerd. Denk maar aan een aangifte die binnenkomt, een betaling die moet worden gedaan, een taak die is uitgevoerd, &#8230; Dit zijn allemaal &#8220;gebeurtenissen&#8221; die in de business zelf voorkomen en aldus <em>business events</em>. Eén van de taken die zou moeten gebeuren aan de start van elke analyse, is de tijd nemen om aan <strong><a href="/radar-2021/business-radar-2021/" data-type="page" data-id="15411">Event Storming</a></strong> te doen: een soort brainstorm naar alle business events die zich in een bepaald process of domein afspelen. Daarna kan de functionele analyse hier mee verder gaan om te bepalen hoe de communicatie tussen de te ontwikkelen systemen zich zal afspelen en hoe de business processen zullen worden geïmplementeerd.</p>



<p class="justify-text">Op IT vlak zullen de business events, en daarbijkomend waarschijnlijk nog een aantal eerder technische events, zich dan uiteindelijk vertalen in de events die over de bus worden gestuurd en deel kunnen gaan uitmaken van een ecosysteem van herbruikbare events. Daartoe is het ook echter van belang dat de events, net zoals herbruikbare APIs, <em>gecatalogiseerd en goed gedocumenteerd</em> worden, zodat er maximaal voordeel uit het bestaan van deze events kan worden gedistilleerd in nieuwe toepassingen. Wat we dus willen zeggen met &#8220;first class citizen&#8221;, is dat events op dezelfde manier zouden moeten worden behandeld als APIs, in een Event-first strategie. We willen echter niet afdoen van APIs, daarom wordt het een <strong>API+Event-first strategie</strong>.</p>



<h3 class="wp-block-heading">Standaarden voor Asynchrone APIs</h3>



<p>Zoals daarnet aangehaald, zijn er op technisch vlak dus ondertussen verschillende goed ingeburgerde technologieën om asynchrone communicatie te voorzien tussen systemen, en waarmee men dus Events kan ondersteunen. <a href="/de-stille-cloud-machtsgreep/" data-type="post" data-id="5543">De Cloud</a> heeft deze evolutie enorm versneld. We sommen er een aantal op:</p>



<div class="wp-block-image"><figure class="alignright size-full"><a href="https://www.asyncapi.com/blog/openapi-vs-asyncapi-burning-questions"><img loading="lazy" decoding="async" width="296" height="235" src="/wp-content/uploads/2021/11/asyncopenapi.jpg" alt="" class="wp-image-16706"/></a><figcaption>Figuur 2: AsyncAPI, de veelbelovende industriestandaard voor Event Driven APIs, vult perfect OpenAPI aan (de standaard voor REST).</figcaption></figure></div>



<ul class="justify-text wp-block-list"><li><strong>Webhooks / REST hooks</strong>. <a href="https://zapier.com/blog/what-are-webhooks/">Ook wel reverse APIs genoemd</a>. Via webhooks kan men nog steeds RESTful werken: er wordt een API aangeboden waar een client een adres van een zogenaamde &#8220;callback API&#8221; kan gaan posten. Later zal de server via dit adres de client kunnen antwoorden. Het voordeel van deze manier van werken is dat men ze op kan laten gaan in de RESTful aanpak. Het nadeel is dat er nog steeds van een synchrone connectie sprake is op het moment van de registratie en op het moment van de callback. Daarnaast is de performantie en veiligheid ook minder dan met de andere methodes.</li><li><strong>Websockets</strong>. Dit is het <a href="https://en.wikipedia.org/wiki/WebSocket">hippe nieuwe protocol voor de browser</a>, waarmee deze een full-duplex kanaal met een webserver kan onderhouden. Full-duplex will zeggen dat men in beide richtingen kan communiceren en dat eender welke kant de communicatie kan starten. Op deze manier kan men dus een webtoepassing in de browser live updaten via events die van de server komen. Deze technologie is dus specifiek nuttig voor het UI-gedeelte van een gedistribueerd systeem: ze zorgt ervoor dat de asynchrone communicatie tot bij de eindgebruiker kan worden gebracht.</li><li><strong>Server Side Events</strong>. Dit is <a href="https://www.w3schools.com/html/html5_serversentevents.asp">een specificatie ingebakken</a> in <a href="/html-5-een-rijke-ervaring-zonder-plugins/" data-type="post" data-id="1426">HTML 5</a>, en daardoor compatibeler dan het nieuwere websockets. Het betreft echter éénrichtingsverkeer, maar dan van de server naar de clients, waardoor men dus een eenvoudigere manier heeft om toch events naar een browser te sturen.</li><li><strong>GraphQL</strong>. Een vrij recente query taal om APIs te beschrijven en bijhorende runtime. Deze technologie wordt gepromoot als meer gericht op de client dan op de server. Dit is omdat de client precies kan uitdrukken wat hij van de server wil krijgen, in plaats van enkel gebruik te kunnen maken van op voorhand vastgelegde zaken, zoals in REST. <a rel="noreferrer noopener" href="https://www.mobilelive.ca/blog/graphql-vs-rest-what-you-didnt-know/" target="_blank">Dit is dus in principe eerder een concurrent voor REST</a>. Je kan echter in GraphQL zogenaamde &#8220;subcriptions&#8221; aanmaken, waardoor de server je op de hoogte kan houden van een aantal zaken, en aldus is ook hier sprake van asycnhrone communicatie waarmee men aan EDA kan doen.</li><li><strong>gRPC</strong>. Dit is een raamwerk dat wordt gepromoot door de Cloud Native Computing Foundation (CNCF). Het is bedoeld om performant Remote Procedure Calls (RPCs) te kunnen maken en aldus eveneens een concurrent voor REST. <a href="https://grpc.io/">gRPC</a> bieft een streaming API aan (<a href="/de-reactive-hype/" data-type="post" data-id="14280">erg handig bij gebruik van de Reactive principes</a>), waarmee ook asynchrone stromen van berichten (en dus ook Events) kunnen worden behandeld.</li><li><strong>CloudEvents</strong>. Ook dit is een <a href="https://cloudevents.io/">initiatief</a> van de &#8220;Serverless Working Group&#8221; van de CNCF. Het betreft een standaardisering van het beschrijven van events op Publisher niveau, waarbij men zich vooral richt op standaard manieren om de metadata te beschrijven. Een jaar geleden kwam versie 1.0.1 uit. Men werkt verder aan verschillende SDK&#8217;s voor talen en er zijn ook specificaties van hoe de standaard te koppelen aan bepaalde technologieën, zoals Event Brokers (de technologie achter de EventBus).</li><li><strong>AsyncAPI</strong>. <a href="https://www.asyncapi.com/">Dit initiatief is de industriestandaard aan het worden. AsyncAPI</a> doet voor EDA wat <a href="https://www.openapis.org/">OpenAPI</a> reeds doet voor RESTful APIs; de twee worden samen ondersteund door de Linux Foundation. Het betreft hier een specificatie van zowel de Events zelf, als de producers en consumers ervan, op een manier die door een computer kan worden verwerkt. Daardoor kan men dan automatisch goede documentatie genereren, aslook stubs voor code, die kan worden gebruikt in de systemen die met de Events zullen omgaan. Deze specificatie gaat veel verder dan CloudEvents, en trekt ook meer aandacht van developers. Ze zit ondertussen aan versie 2.2.0. Op dit moment zijn er ook al verschillende technologieën ondersteund voor de effectieve implementatie van de Events: o.a. Apache Kafka, AMQP, IBM MQ, MQTT, SNS, WebSockets, en JMS.</li></ul>



<p class="justify-text">Ondanks alle nieuwe ontwikkelingen op gebied van EDA, willen we hier echter niet gaan beweren dat alles nu Event-Driven moet worden, en al zeker niet dat we APIs zouden moeten afschaffen. Events zijn, evenmin as APIs, het antwoord op alles. Ook EDA heeft een aantal nadelen: de asynchrone communicatie inherent aan Events, zorgt ervoor dat systemen die events van elkaar willen gebruiken, op een bepaald niveau &#8220;Eventually Consistent&#8221; worden, en dus niet meer transactioneel zijn. Dit kan in principe voordelig zijn op een aantal punten, maar het zorgt ervoor dat het minder makkelijk is om erover te redeneren indien men gewend is dat alles ten allen tijde consistent wordt gehouden. Het zijn dus systemen die soms iets ingewikkelder in elkaar zitten en minder gemakkelijk te voorspellen zijn: je hebt, binnen één systeem, geen directe controle over wat er allemaal zal gebeuren als gevolg van een Event dat je de wereld instuurt (je hebt enkel controle over wat je kan doen met inkomende Events). Dit alles zorgt ervoor dat het niet altijd even gemakkelijk is om zulke (groepen) systemen te testen en debuggen, temeer omdat er ook minder veel mensen te vinden zijn die er ervaring mee hebben.</p>



<p class="justify-text">Maar, zoals reeds gezegd, EDA kan heel krachtig zijn, en leunt vaak sterk aan bij het business model. Het ideale antwoord over wat we nu best gebruiken, zal dus, zoals gewoonlijk, ergens in het midden liggen&#8230;</p>



<h2 class="wp-block-heading">De gebalanceerde aanpak: APIs plus Events</h2>



<p class="justify-text">Zoals we hebben aangetoond in de vorige sectie, heeft een Eventgedreven aanpak een aantal sterke pluspunten; niet in het minst een resiliënter systeem dat beter voorzien is op toekomstige aanpassingen en uitbreidingen en dus tot op business niveau agile is. Uiteraard zijn er ook een aantal beperkingen, en we gaan dus zeker geen pleidooi houden om vanaf nu alle services zuiver Event-driven te maken. Het antwoord zal een hybride aanpak zijn.</p>



<div class="wp-block-image"><figure class="aligncenter size-full"><a href="/wp-content/uploads/2021/11/hybrid.png"><img loading="lazy" decoding="async" width="855" height="422" src="/wp-content/uploads/2021/11/hybrid.png" alt="" class="wp-image-16681" srcset="https://www.smalsresearch.be/wp-content/uploads/2021/11/hybrid.png 855w, https://www.smalsresearch.be/wp-content/uploads/2021/11/hybrid-300x148.png 300w, https://www.smalsresearch.be/wp-content/uploads/2021/11/hybrid-768x379.png 768w" sizes="auto, (max-width: 855px) 100vw, 855px" /></a><figcaption>Figuur 3: De webstore, met een combinatie van synchrone API calls en asynchrone Events</figcaption></figure></div>



<p class="justify-text">We gaven vroeger al een <a href="/architecturale-evoluties-deel-2/" data-type="post" data-id="11475">een eerder abstract voorbeeld van hoe deze verschillende zaken kunnen worden gecombineerd in onze blogs</a>. Nu zullen we dit iets concreter maken: in figuur 3 overlopen we hetzelfde voorbeeld als dat van figuur 1, maar dan met een combinatie van API gebruik en Events.</p>



<ol class="justify-text wp-block-list"><li>De gebruiker logt in (API call naar Customer; &#8220;Login&#8221;-Event 1 )</li><li>De Cart Service ziet event 1 en verstuurt zelf een event met de vorige inhoud van het karretje (&#8220;Cart Updated&#8221;-Event 2 )</li><li>De front-end ziet event 2 en laat de kar-inhoud zien aan de gebruiker</li><li>De gebruiker winkelt (API calls naar Catalog; &#8220;Product Chosen&#8221;-Event 3 )</li><li>De Cart Service ziet event 3 en past het karretje aan (nogmaals &#8220;Cart Updated&#8221;-Event zoals 2, niet apart getoond)</li><li>Ook Checkout ziet de &#8220;Cart Updated&#8221; events en bewaart de aankopen (&#8220;Cart Updated&#8221;-Event zoals 2, niet getoond)</li><li>De gebruiker wil een checkout doen (API calls naar checkout en shipping, voor de verzendingskost)</li><li>De gebruiker bevestigt het order (API call naar checkout; &#8220;Order Confirmed&#8221;-Event 4 )</li><li>Event 4 wordt opgepikt door Cart (kar leegmaken) en Orders (order bewaren)</li><li>Event 4 wordt eveneens gezien door Inventory (Inventory wordt gereserveerd)</li><li>De gebruiker wordt ook omgeleid naar Payment en voert de betaling uit (API call naar payment)</li><li>Er gebeurt een succesvolle betaling (&#8220;Payment Received&#8221;-Event 5 )</li><li>De Orders Service ziet event 5 en stuurt zelf een event (&#8220;Order Ready-to-Pack&#8221;-Event 6 )</li><li>De Shipping Service vangt event 6 en regelt het versturen bij de koerier</li><li>Ook de Inventory service ziet event 6 (Inventory wordt finaal aangepast en pak-opdracht gaat naar magazijn)</li><li>De klant die zijn orders raadpleegt, kan dat nog via een API call (De Orders Service kunnen we via <a href="/geavanceerd-event-driven-engineering/" data-type="post" data-id="9041">CQRS</a> bouwen: het deel dat actief zaken verwerkt en business beslissingen neemt is volledig Event-Driven; een tweede component van de service observeert alle gerelateerde events en bouwt een resulterend relationeel model op, dat makkelijk kan worden gequeried)</li><li>Hier stopt het voorbeeld van Fig. 1, maar we zouden nog verder kunnen gaan: wanneer het pakket klaar staat, zal er opnieuw een event hiervoor zijn en kan de effectieve verzending gebeuren via de koerier. Daarna zijn er nog tracking events, enz.</li></ol>



<p class="justify-text">Een aantal extra opmerkingen betreffende deze manier van aanpakken:</p>



<ul class="justify-text wp-block-list"><li>In dit scenario zien we dat de front-end meer rechtstreeks gebruik maakt van een aantal achterliggende diensten, en er dus in principe van afhankelijk wordt. We moeten echter onthouden dat dit geen alles-of-niets afhankelijkheid is, zoals een aantal van de point-to-point verbindingen in het eerste scenario. De afhankelijkheid geldt enkel voor welbepaalde functionaliteiten, die afzonderlijk van elkaar onbeschikbaar kunnen zijn.</li><li>We hebben hier ook de mogelijkheid de betaling achteraf in orde te brengen indien de betaling zou mislukken of de Payment Service niet beschikbaar is. Shipping schiet pas in actie nadat het event &#8220;Payment Received&#8221; is gepasseerd. In beide scenario&#8217;s hebben we eventuele 3rd party API calls naar Betalingsfirma&#8217;s (b.v. PayPal) achterwege gelaten, wat een extra kans op falen introduceert. In het eerste scenario zou hierdoor de volledige transactie van de bestelling mislukken (hetgeen ook het geval is bij vele echt bestaande webshops, maar b.v. niet bij een geavanceerde webshop als Amazon, waar men de betaling asynchroon achter de schermen kan regelen).</li><li>Zowel de Cart als de Checkout service houden een winkelmandje bij, maar toch verschillen ze. De Cart service is verantwoordelijk voor de opslag van het mandje overheen verschillende gebruikersessies (en kan eventueel nog wishlists en favorieten en dergelijke functionaliteiten aanbieden). De Checkout service houdt het enkel gedurende één sessie bij tot het een effectief order wordt, en voegt de bestemming en de verzendingskost toe. We zouden hier echter kunnen overwegen om de checkout functies ook in Cart onder te brengen.</li><li>Merk op dat we in geen van beide scenario&#8217;s (zuivere API aanpak en hybride) een laatste check van de inventory doen bij het bestellen. Indien echt nodig op business niveau, zouden we dit in beide gevallen synchroon (en transactioneel) doen (met gevolgen voor de resiliency en klantentevredenheid). We kiezen er echter voor op business niveau dit niet te doen en een eventueel stocktekort op business niveau aan te pakken (<a href="/eventual-consistency-1/" data-type="post" data-id="15544">zie het voorbeeld in de blogpost over Eventual Consistency</a>).</li><li>Om de afhankelijkheid van de externe shipping API te reduceren, kunnen we er in beide scenario&#8217;s voor zorgen dat we de prijzen cachen, of zelf op business niveau vastleggen zonder dit dynamisch op te vragen bij de koerier. Op die manier bestaat de afhankelijkheid enkel op het moment van het effectieve aanmaken van de verzending (en later bij het traceren; wat in principe ook best Event-Driven is, maar in externe APIs is dit vaak niet voorzien).</li></ul>



<p class="justify-text">Zoals we kunnen zien aan de hand van dit voorbeeld, kan een hybride aanpak interessante voordelen hebben: de services zijn heel wat minder sterk afhankelijk van elkaar en zijn zelfstandiger. Men kan kiezen op welke events te reageren en welke events uit te sturen, zonder een API te wijzigen; de service kan op deze manier makkelijker evolueren of verplaatst worden. Er is ook een verbeterde resiliëntie: wanneer een service uitvalt, blijven een aantal events onbehandeld. Maar wanneer de service terug online komt, kan dit werk worden ingehaald en gaat het proces gewoon verder. Er is dus sprake van tijdelijke degradatie en uitstel, maar niet van verloren gegane transacties of een cascade van falen. Men moet er wel op letten dat de EventBus een hoog niveau van beschikbaarheid heeft, net zoals de <a href="/productiviteitsverhoging-met-paas/" data-type="post" data-id="5995">andere middleware platformen</a> waar men de applicaties op bouwt, en de onderliggende infrastructuur.</p>



<h2 class="wp-block-heading">Conclusie</h2>



<p class="justify-text">Een Software Development strategie gebaseerd op het bouwen van RESTful APIs is een goed startpunt. We mogen ons echter niet blindstaren op de voordelen van REST en alleen maar van deze oplossing gebruik maken.</p>



<p class="justify-text">Een Eventgedreven aanpak heeft een aantal sterke pluspunten; niet in het minst een resiliënter systeem dat beter voorzien is op toekomstige aanpassingen en uitbreidingen, en dus tot op business niveau agile is.</p>



<p class="justify-text">In een optimaal gebalanceerde Softwareontwikkelingsstrategie is dus zeker ook ruimte voorzien voor asynchrone communicatie en eventual consistency, door gebruik te maken van Event Driven Architecture. Het is dan ook van groot belang hiermee rekening te houden vanaf het vormen van een visie, tijdens de business analyse en daarna doorheen het hele ontwikkelingsproces.</p>


]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Eventual Consistency &#8211; Een nog te weinig ontgonnen Principe</title>
		<link>https://www.smalsresearch.be/eventual-consistency-1/</link>
		
		<dc:creator><![CDATA[Koen Vanderkimpen]]></dc:creator>
		<pubDate>Mon, 12 Apr 2021 09:47:10 +0000</pubDate>
				<category><![CDATA[[NL]]]></category>
		<category><![CDATA[Blog post]]></category>
		<category><![CDATA[CAP]]></category>
		<category><![CDATA[cloud computing]]></category>
		<category><![CDATA[Eventual Consistency]]></category>
		<category><![CDATA[High Availability]]></category>
		<category><![CDATA[methodology]]></category>
		<category><![CDATA[Resilience]]></category>
		<category><![CDATA[Software architectures]]></category>
		<category><![CDATA[software engineering]]></category>
		<guid isPermaLink="false">/?p=15544</guid>

					<description><![CDATA[Eventual Consistency is dé truc waarmee vele NOSql databases hun beschikbaarheid gevoelig kunnen verbeteren. Maar kunnen we dit principe ook doortrekken naar de rest van de architectuur, en misschien zelfs laten meespelen op business niveau? Of is het sop de kool niet waard, en moeten we kiezen voor de eenvoudig bruikbare garanties die Strong Consistency [&#8230;]]]></description>
										<content:encoded><![CDATA[
<div class="wp-block-image is-style-default"><figure class="alignleft size-large is-resized"><a href="/wp-content/uploads/2021/04/Availability1.png"><img loading="lazy" decoding="async" src="/wp-content/uploads/2021/04/Availability1.png" alt="" class="wp-image-15833" width="158" height="158" srcset="https://www.smalsresearch.be/wp-content/uploads/2021/04/Availability1.png 536w, https://www.smalsresearch.be/wp-content/uploads/2021/04/Availability1-150x150.png 150w, https://www.smalsresearch.be/wp-content/uploads/2021/04/Availability1-300x300.png 300w" sizes="auto, (max-width: 158px) 100vw, 158px" /></a></figure></div>



<p class="justify-text">Eventual Consistency is dé truc waarmee vele NOSql databases hun beschikbaarheid gevoelig kunnen verbeteren. Maar kunnen we dit principe ook doortrekken naar de rest van de architectuur, en misschien zelfs laten meespelen op business niveau? Of is het sop de kool niet waard, en moeten we kiezen voor de eenvoudig bruikbare garanties die Strong Consistency ons biedt?</p>



<span id="more-15544"></span>



<p class="justify-text">In dit blogartikel gaan we het concept <a href="https://en.wikipedia.org/wiki/Eventual_consistency">Eventual Consistency</a> (EC) verder uitdiepen. Wat betekent het precies? Wat zijn goede voorbeelden? En &#8211; uiteraard &#8211; wat hebben we er precies aan? Wanneer wordt dit principe nuttig?</p>



<h2 class="wp-block-heading">Wat is Eventual Consistency?</h2>



<p class="justify-text">Het principe / model van Eventual Consistency bestaat reeds lang, maar werd vooral bekend door het gebruik ervan in <a href="/nosql-databases-simpel-performant-schaalbaar/" data-type="post" data-id="1105">NOSql databases</a>. Deze databases waren een broodnodige revolutie toen populaire webtoepassingen een zodanig grote schaal kregen dat traditionele databases ontoereikend bleken.</p>



<p class="justify-text">Het grote voordeel van deze databases is namelijk dat ze enorm schaalbaar zijn en, zelfs bij het voorkomen van netwerkfalen, blijven werken. Het is precies het EC model dat hiervoor zorgt. Maar wat doet dit principe nu juist?</p>



<p class="justify-text">Het Eventual Consistency model is van toepassing op gedistribueerde systemen; m.a.w. systemen met meerdere nodes, verbonden door een netwerk. Een systeem dat als consistentiemodel EC heeft, zal ervoor zorgen dat een update aan een gegeven na verloop van tijd op alle nodes zal geraken. Tot die tijd kan het zijn dat we op bepaalde nodes nog de vorige waarde van het gegeven uitlezen.</p>



<p class="justify-text">Dit is natuurlijk een erg zwakke garantie, maar <strong>ze laat toe dat de nodes afzonderlijk kunnen blijven werken, zelfs indien het netwerk ertussen faalt, of indien een aantal nodes een tijdlang uitgeschakeld worden</strong>. Wanneer alles terug in orde geraakt, zal het systeem ervoor zorgen dat alles overal terug up-to-date is.</p>



<p class="justify-text">Eventual Consistency wordt ook wel <em>Optimistische Replicatie</em> genoemd. Wanneer een EC systeem de nodige updates heeft verwerkt en terug consistent is, zeggen we dat het systeem is <em>geconvergeerd</em>. De tijd die verstrijkt tussen een update en het convergeren, noemen we de <em>inconsistency window</em>. Deze willen we natuurlijk liefst zo kort mogelijk houden. In de huidige state of the art zal dit in de meeste gevallen, indien er geen falende nodes of netwerkpartities zijn, slechts milliseconden tot seconden duren.</p>



<figure class="wp-block-image size-full is-resized justify-text"><a href="/wp-content/uploads/2021/04/Availability2.png"><img loading="lazy" decoding="async" src="/wp-content/uploads/2021/04/Availability2.png" alt="" class="wp-image-15808" width="578" height="372" title="" srcset="https://www.smalsresearch.be/wp-content/uploads/2021/04/Availability2.png 474w, https://www.smalsresearch.be/wp-content/uploads/2021/04/Availability2-300x193.png 300w" sizes="auto, (max-width: 578px) 100vw, 578px" /></a><figcaption>Figuur 1: Het principe van Eventual Consistency geïllustreerd. Nodes 1 en 2 vormen samen ons gedistribueerd systeem. Op tijd t1 doet client 1 een update. Enige tijd later, op tijd t2, vraagt client 2 hetzelfde gegeven op; dit zal echter nog de oude versie zijn, vermits de update van node 1 de andere node slechts op tijd t3 bereikt. Wanneer het gegeven nogmaals wordt opgevraagd, op tijd t4, is het up-to-date. De tijd tussen t1 en t3 noemen we de &#8220;inconsistency window&#8221;, aangegeven door de accolade.</figcaption></figure>



<p class="justify-text">Natuurlijk maakt het Eventual Consistency model het ook wel moeilijker om te redeneren en om te gaan met de data. Zo zijn er een aantal problemen waar developers een antwoord op zullen moeten hebben, indien ze EC willen gebruiken. Wat doe je bijvoorbeeld met clients die een node consulteren die nog niet de laatste nieuwe gegevens heeft? En &#8211; erger nog &#8211; wat als twee nodes een update binnenkrijgen voor hetzelfde gegeven, vóór ze elkaar op de hoogte hebben gebracht?</p>



<p class="justify-text">De meeste developers zijn gewend aan de luxe van &#8220;Strong Consistency&#8221; bij de systemen waarop ze verder bouwen. Deze tegenhanger van EC garandeert dat indien er een update is gebeurd, élke leesopdracht die daarna nog volgt deze update zal zien. Daarenboven is het in zo&#8217;n systeem niet mogelijk om conflicterende updates te doen aan éénzelfde gegeven.</p>



<p class="justify-text">Je kan natuurlijk al aanvoelen dat Strong Consistency zijn eigen problemen heeft: wanneer de schaal groter en groter wordt, kan het steeds vaker voorkomen dat clients moeten wachten, omdat het systeem bezig is ervoor te zorgen dat alle nodes consistent zijn. Het systeem wordt daardoor dus minder beschikbaar. Of nog: <a href="/newsql-getest-en-goedgekeurd/" data-type="post" data-id="13705">onvoldoende nodes kunnen met elkaar communiceren om consistentie te garanderen</a>, en het volledige systeem wordt onbeschikbaar. Dit is natuurlijk precies de te maken keuze die wordt geïllustreerd door het <a href="/newsql-een-upgrade-voor-je-oude-database/" data-type="post" data-id="13610">CAP</a> / <a href="/newsql-getest-en-goedgekeurd/" data-type="post" data-id="13705">PACELC</a> theorema, waarover we reeds eerder hebben <a href="/high-availability-wc-papier/">geblogd</a>. Een gedistribueerd systeem moet altijd Partitietolerant zijn (P), dus daarna blijft nog de keuze over om te focussen op Consistentie (C) of Availability (A), maar alle drie samen gaat niet (zelfs de laatste evolutie in databases, de <a href="/newsql-een-upgrade-voor-je-oude-database/" data-type="post" data-id="13610">NewSql databases</a>, maken hierin de keuze voor consistentie, al voorzien ze heel wat verbeteringen om toch nog zo beschikbaar mogelijk te zijn).</p>



<h2 class="wp-block-heading">Voorbeelden</h2>



<p class="justify-text">Buiten het typische voorbeeld van NOSql Databases die EC storage kunnen leveren aan applicaties, kunnen we ook een aantal voorbeelden geven waarbij de EC op een hoger niveau van abstractie zijn werk doet binnen een applicatie, en zelfs op business niveau zijn impact heeft.</p>



<h3 class="wp-block-heading">1. Domain Name System (DNS)</h3>



<p class="justify-text"><a href="https://en.wikipedia.org/wiki/Domain_Name_System">DNS</a>, een zeer bekend systeem in de informatica, koppelt internet domeinnamen aan IP-adressen. Het is een hiërarchisch systeem, doch grotendeels gedecentraliseerd. Noodzakelijkerwijs moet de data sterk verspreid en gerepliceerd worden, want het volledige internet maakt gebruik van dit systeem, en geen enkele individuele machine of zelfs cluster zou deze schaal aankunnen.</p>



<p class="justify-text">Wanneer er een update gebeurt binnen dit systeem, zal dit eerst op één server gebeuren. Deze server (de &#8220;authoritatieve server&#8221; voor een bepaald domein) heeft dan het correcte IP-adres dat bij een domeinnaam hoort, maar andere servers nog niet. Na verloop van tijd zal de informatie zich echter verspreiden doorheen het hele DNS systeem. Uiteindelijk zullen alle servers die de desbetreffende domeinnaam stockeren, hun cache laten verlopen, en de meest recente versie opvragen, en op deze manier is DNS dus eventually consistent.</p>



<p class="justify-text" id="justify-text">Zonder verdere maatregelen, zullen clients die toevallig naar een bepaalde site willen surfen, terwijl de cache van hun DNS server nog naar oude data verwijst, niet naar het nieuwe IP adres kunnen gaan. Met een goed beheer van je DNS data kan je dit echter voorkomen (b.v. op het oude IP adres nog een tijdlang een redirect server plaatsen).</p>



<h3 class="wp-block-heading">2. Webwinkel</h3>



<p class="justify-text">Voor een webwinkel kan elke minuut dat mensen geen bestellingen kunnen doen, een groot verlies betekenen. Beschikbaarheid (van het winkelgedeelte op zijn minst) is dus cruciaal.</p>



<p class="justify-text">Om hiervoor te zorgen, kan er worden gebruik gemaakt van Eventual Consistency in verschillende gradaties. Men zou bijvoorbeeld kunnen stellen dat men veranderingen in het inventorysysteem (b.v. hoeveel van dit artikel is nog in stock?) slechts met enige vertraging laat doorsijpelen tot het frontend systeem, dat de clients bedient, die bezig zijn met winkelen. Je zou dus iets in je winkelkarretje kunnen leggen dat niet meer in stock is. Op het moment echter van de eigenlijke bestelling, zou men wel via een transactie kunnen werken, waarbij men effectief de huidige inventaris gaat nakijken alvorens de bestelling te laten doorgaan. Indien het artikel er niet meer is, krijgt de klant op dat moment een foutboodschap met verontschuldigingen en b.v. de optie om bericht te krijgen wanneer de stock is bijgevuld.</p>



<p class="justify-text">Op deze manier voorziet men reeds een loskoppeling tussen het winkelsysteem zelf, en de inventory backend, waardoor de eerste beschikbaar blijft, zelfs wanneer de laatste niet goed werkt.</p>



<p class="justify-text">Men kan hier de Eventual Consistency zelfs nog verder doortrekken: we laten de bestelling doorgaan zonder de inventory op te nemen in de transactie, en we brengen deze pas later (eventually) up-to-date. Zo kan een klant een item zelfs bestellen indien het niet meer in stock is. Uiteraard zal er echter wel iets moeten gebeuren in zo een geval. We kunnen dan op zoek  gaan naar mitigerende processen op business niveau. Er kan bijvoorbeeld een email gestuurd worden met verontschuldigingen: &#8220;spijtig genoeg moeten we dit artikel nabestellen en zal het dus iets later zijn; u krijgt de verzendingskosten terug of mag de bestelling alsnog annuleren&#8221;. Of nog: &#8220;We kunnen dit helaas nu niet leveren; we annuleerden uw bestelling en u krijgt een waardebon&#8221;. Hier zijn tal van mogelijkheden, de ene al klantvriendelijker dan de andere, waaruit de business kan kiezen als strategie.</p>



<h3 class="wp-block-heading">3. Het bancair systeem</h3>



<p class="justify-text">Het lijkt misschien contra-intuïtief, maar een aantal aspecten van het bancair systeem, bijvoorbeeld bij het &#8220;settlen&#8221; van rekeningen, zijn via EC geregeld, en dit was noodzakelijkerwijs zelfs al zo voordat er sprake was van computers!</p>



<p class="justify-text">Wanneer in de IT een voorbeeld van de bankwereld wordt gebruikt, zal men typisch de atomaire transactie uitleggen die moet gebeuren bij een overschrijving: indien één rekening gedebiteerd wordt, moét de andere gecrediteerd worden, of vice versa. Dit is natuurlijk een voorbeeld van Strong Consistency.</p>



<p class="justify-text">Maar er zijn tal van manieren waarop de stand van een rekening niet overeenkomt met wat de waarde ervan zou moeten zijn, rekening houdend met alle transacties die al hebben plaatsgevonden of nog moeten plaatsvinden. Zo kan ik b.v. allerlei online zaken bestellen op zondag, terwijl ik zaterdag al ben gaan winkelen. De bancontact transactie van de winkel is nog niet doorgekomen, en het saldo op mijn rekening is dus een pak hoger, waardoor ik meer geld kan uitgeven dan ik heb. Op maandag wordt alles dan vereffend en komt mijn rekening onder nul. Gelukkig werd op vrijdag mijn loon gestort en komt dit óók maandag tot uiting op mijn rekening. Net op tijd om de cheque aan te kunnen die geïnd zal worden op dinsdag, maar die ik reeds een week geleden aan iemand heb gegeven voor een grote aankoop, met de vraag of die even wou wachten met het innen.</p>



<p class="justify-text" id="justify-text">Er kunnen dus allerlei zaken gebeuren die het saldo van een rekening beïnvloeden en die soms zelfs het saldo van de rekening nakijken, zonder dat het saldo al met al deze zaken rekening houdt. De rekeningstand is dus &#8220;eventually consistent&#8221;: uiteindelijk komen alle transacties erop terecht, maar dit kan even duren.</p>



<p class="justify-text">De bankwereld heeft geen probleem met het bestaan van dit soort inconsistenties in hun systeem, die zelfs op business niveau zichtbaar zijn. Misbruik ervan wordt dan ook vrijwel geheel vermeden door allerlei provisies (eveneens op business niveau): b.v. wetten die fraude strafbaar maken.</p>



<h3 class="wp-block-heading">4. Onze sector?</h3>



<p class="justify-text">We kunnen niet direct voorbeelden geven van zaken die binnen onze sector via eventual consistency zijn geïmplementeerd, maar we kunnen wel eens verkennen waar er eventueel mogelijkheden bestaan om dit in de toekomst te gaan doen.</p>



<p class="justify-text">Als we de typische workflows binnen de overheid in beschouwing nemen, zien we dat er geregeld processen zijn waarbij iets wordt aangevraagd, of een dossier wordt ingediend, dat dan later wordt nagekeken en wordt verwerkt met menselijke tussenkomst. Dit is een heel goede indicator dat we misschien wel EC kunnen gebruiken, gezien er reeds een natuurlijke vorm van uitstel in het proces zit. Hetzelfde zien we bij die processen waarin gegevens verplicht moeten worden ingediend, maar niet noodzakelijkerwijs onmiddellijk worden behandeld door de desbetreffende overheidsdienst.</p>



<p class="justify-text">Kijken we anderzijds naar de gezondheidssector (eHealth). Hier is het uiteraard cruciaal dat de toegang tot patiëntendossiers een zo hoog mogelijke beschikbaarheid biedt. Maar is het absoluut noodzakelijk dat de informatie tot op de seconde up-to-date is? Persoonlijk zou ik denken van niet. Indien mijn huisarts mijn dossier een half uurtje geleden heeft geüpdated, is het allicht niet erg dat ze dit in het ziekenhuis nog niet kunnen zien. De volgende dag, als ik naar het ziekenhuis ga, wil ik dit uiteraard wel, maar tegen dan heeft men tijd genoeg gehad om alle nodes van het systeem voldoende met elkaar te laten communiceren.</p>



<p class="justify-text">En wat met apothekers die de <a href="https://www.riziv.fgov.be/nl/themas/kost-terugbetaling/verzekerbaarheid/Paginas/default.aspx">verzekerbaarheid</a> van iemand moeten nagaan? Het is cruciaal dat deze informatie beschikbaar is wanneer iemand een medicijn komt kopen. Maar de kans dat dit gegeven is veranderd gedurende het voorbije half uur is enorm klein; ook hier kan men dus overweg met gegevens die niet tot op de seconde up-to-date zijn. Voeg daarbij eventueel een mitigerende regel op business niveau toe, voor de minieme hoeveelheid uitzonderingen waarbij men toch een medicijn zonder korting zou verschaffen terwijl de klant hier wel recht op had (b.v. een terugbetaling achteraf, wanneer dit wordt vastgesteld dankzij de zich convergerende gegevens).</p>



<h2 class="wp-block-heading">Evaluatie en Besluit</h2>



<p class="justify-text">De voorbeelden maakten het reeds duidelijk: Eventual Consistency kan ervoor zorgen dat een systeem gewoon blijft doorwerken, zelfs wanneer er zaken mislopen. Op die manier kan de resiliëntie gevoelig worden verhoogd. Er moet in zo&#8217;n geval echter wel met een aantal inconsistenties in de data worden rekening gehouden, op IT vlak óf op business vlak, en dit maakt het complexer om over deze systemen te redeneren en om deze te bouwen. En uiteraard heeft een complex systeem ook een verhoogde kans op falen, net door de verhoogde kans op fouten die deze complexiteit met zich meebrengt.</p>



<p class="justify-text">We zullen dan ook een afweging moeten maken, <em>samen met de business</em>, om te zien waar de prioriteiten liggen. Hoe belangrijk is het dat dit systeem een beschikbaarheid heeft van vele negens (99,9% beschikbaarheid, &#8220;triple nine availability&#8221;, is b.v. nog haalbaar zonder EC voor een niet al te groot systeem)? Hoeveel data zal het systeem op termijn gaan bevatten / behandelen? In welke mate zal het moeten schalen voor gebruik door vele gelijktijdige clients?</p>



<p class="justify-text">We kunnen stellen dat Eventual Consistency enorm vruchten begint af te werpen, wanneer men met systemen te maken krijgt van een redelijk grote schaal. Voor dit soort systemen wordt het sowieso complex om ze draaiende te houden en zal de bijkomende complexiteit die EC met zich meebrengt, relatief een minder groot verschil maken. Het voordeel van de verhoogde resiliëntie zal in dat geval meer doorwegen. Sommige experts stellen zelfs dat sterke consistentie een sprookje wordt vanaf een bepaalde (erg grote) schaal, en dat men dus op een bepaald moment altijd naar eventual consistency zal moeten grijpen bij een sterk groeiend systeem.</p>



<p class="justify-text">Indien men echter met een klein systeem zit, b.v. bedoeld voor intern gebruik en met beperkte volumes aan data, dan zal het sop de kool meestal niet waard zijn en kan men, voor het gemak, best gebruik maken van Strong Consistency, wat het veel eenvoudiger maakt voor de ontwikkelaars van het systeem om het te bouwen en onderhouden.</p>



<p class="justify-text">Ten slotte kan men best bij elk project van enige omvang eens <em><strong>kritisch kijken naar de business processen</strong></em> die worden gedigitaliseerd. Vergen alle te implementeren functionaliteiten daadwerkelijk sterke consistentie doorheen het volledige proces? Moet alle data binnen de paar seconden gegarandeerd overal up-to-date zijn? Of zijn er misschien van nature stappen aanwezig waar menselijke tussenkomst is vereist, en men dus sowieso met wachttijden zit? Bestaan er eventueel op business niveau reeds mitigerende processen om om te gaan met een inconcistentie?</p>



<p class="justify-text">Vaak zal men dan zien dat sterke consistentie toch niet nodig is, en zeker niet overheen het volledige systeem, en ontstaan er dus mogelijkheden om de resiliëntie te verbeteren via Eventual Consistency.</p>



<p></p>


]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
