3.3

View in English

3.3 Gedistribueerde systemen

Overzicht en motivatie

Een gedistribueerd systeem is elk systeem waarvan de componenten op meer dan één machine draaien en over een netwerk coördineren. Zodra je een procesgrens over een netwerk overschrijdt, erf je een aantal harde waarheden die binnen één proces simpelweg niet bestaan. Het netwerk is onbetrouwbaar en zijn latentie varieert. Berichten kunnen verloren gaan, gedupliceerd, vertraagd of herordend worden. Externe componenten falen op hun eigen houtje. Er is geen gedeelde klok. De klassieke ”valkuilen van gedistribueerd rekenen” (het netwerk is betrouwbaar, latentie is nul, bandbreedte is oneindig, de topologie verandert nooit) noemen precies de aannames die storingen veroorzaken. Jouw taak is vanaf het begin voor deze werkelijkheden te ontwerpen in plaats van ze tijdens een incident te herontdekken.

Voor een grote organisatie is distributie niet optioneel. Elk systeem dat nationale of wereldwijde schaal bedient, meerdere afdelingen aaneenknoopt of hoge beschikbaarheid nodig heeft, zal zich uitstrekken over veel machines, datacenters en vaak regio’s. Ondernemingen draaien gedistribueerde transactiesystemen, gebeurtenispipelines en deployments over meerdere regio’s. Overheden draaien integraties tussen instanties waar elke instantie haar eigen systemen bezit en niemand het geheel beheerst. Hier toont de kloof tussen een robuust en een broos ontwerp zich als kopstoringen, gemiste uitkeringsbetalingen en regelgevende gevolgen. De technieken in dit hoofdstuk (redeneren over consistentie, idempotentie, herhalingen met backoff, circuit breakers, sagas en gedistribueerde observeerbaarheid) zijn je standaardverdedigingen.

Het moeilijkste aan gedistribueerde systemen is dat falen gedeeltelijk en intermitterend is. Een programma op één machine werkt of crasht. Een gedistribueerd systeem kan half werken: sommige verzoeken slagen, sommige lopen in een time-out en sommige gaan stilletjes verloren, alles tegelijk. Dit hoofdstuk richt zich op het redeneren en de patronen waarmee een groot team systemen kan bouwen die gracieus degraderen en begrijpelijk blijven onder gedeeltelijk falen.

Kernprincipes

  • Het netwerk is niet betrouwbaar. Ontwerp elke externe interactie in de veronderstelling dat ze traag kan zijn, kan falen, kan dupliceren of kan herordenen.
  • Je kunt niet perfecte consistentie en perfecte beschikbaarheid hebben tijdens een partitie. Kies bewust per interactie (CAP/PACELC), en onthoud dat latentie een kost is ook zonder partitie.
  • Maak bewerkingen idempotent. Als een bewerking veilig kan worden herhaald, wordt het meeste gedistribueerde foutafhandelen hanteerbaar.
  • Elke externe aanroep heeft een time-out nodig. Onbegrensd wachten verandert één trage afhankelijkheid in een storing van het hele systeem.
  • Geef de voorkeur aan uiteindelijke consistentie waar het bedrijf het toelaat, maar maak het expliciet. Gebruikers en auditors moeten begrijpen wanneer ze verouderde data kunnen zien.
  • Isoleer falen. Bulkheads en circuit breakers stoppen dat één falend component zich tot alle uitbreidt.
  • Je kunt niet debuggen wat je niet kunt zien. Gedistribueerde stromen vragen gecorreleerde tracing, statistieken en logs over elke hop.
  • “Exactly-once delivery” is een mythe. Exactly-once verwerking is een engineeringprestatie. Ontwerp voor at-least-once met ontdubbeling.

Aanbevelingen

Redeneer over consistentie met CAP en PACELC

De CAP-stelling zegt dat een systeem tijdens een netwerkpartitie moet kiezen tussen consistentie (elke leesactie ziet de laatste schrijfactie) en beschikbaarheid (elk verzoek krijgt een antwoord). PACELC voegt een tweede ruil toe: Else (wanneer er geen partitie is) ruil je nog steeds Latentie tegen Consistentie. Stempel dit niet als label op het hele systeem. Besluit het per bewerking. De saldoovermaking van een bank heeft sterke consistentie nodig en zal weigeren in plaats van dubbele uitgave te riskeren. Een sociale feed of een teller van productweergaven kan veroudering accepteren in ruil voor beschikbaarheid en snelheid. Schrijf op welk consistentiemodel elke datastroom gebruikt (sterk, causaal, read-your-writes of uiteindelijk) zodat niemand een garantie aanneemt die het systeem niet werkelijk biedt.

Bouw idempotentie, time-outs, herhalingen en backoff samen

Behandel deze vier technieken als één pakket. Geef elke externe bewerking een time-out, zodat een vastgelopen afhankelijkheid een thread niet eeuwig kan blokkeren. Herhaal bij falen, maar alleen voor bewerkingen die veilig te herhalen zijn. Veilig te herhalen betekent idempotent: wijs elk verzoek een unieke sleutel toe en laat de ontvanger ontdubbelen, zodat een herhaalde “kaart belasten” niet twee keer belast. Spreid je herhalingen met exponentiële backoff en jitter, zodat je een gesynchroniseerde herhaalstorm vermijdt die een korte hapering in een zelf toegebrachte denial of service verandert. Begrens het aantal herhalingen en het totale tijdbudget, want eindeloos herhalen verplaatst het falen alleen. Zonder idempotentie zijn herhalingen gevaarlijk. Zonder backoff zijn herhalingen destructief.

Voeg circuit breakers en bulkheads toe om cascades te stoppen

Een circuit breaker bewaakt aanroepen naar een afhankelijkheid en “opent” na een drempel aan falen: hij faalt snel gedurende een afkoelperiode in plaats van meer verzoeken op een worstelende service te stapelen, en “half-opent” dan om herstel te testen. Dit stopt de cascade waarbij een trage downstreamservice de threads van elke aanroeper uitput tot het hele systeem vastloopt. Bulkheads partitioneren middelen (threadpools, verbindingspools) zodat verzadiging bij de ene afhankelijkheid de capaciteit die anderen nodig hebben niet kan opeten. Combineer beide met gracieuze degradatie: wanneer een niet-kritieke afhankelijkheid onbeschikbaar is, geef dan gecachete of standaardantwoorden terug in plaats van het hele verzoek te laten falen.

Beheer gedistribueerde transacties met sagas, niet met two-phase commit

Je kunt meestal geen enkele ACID-transactie (Atomicity, Consistency, Isolation, Durability) over meerdere services of databases vasthouden. Gedistribueerde two-phase commit is traag, vergrendelt middelen en snijdt beschikbaarheid af. Gebruik in plaats daarvan het saga-patroon. Modelleer een bedrijfstransactie als een reeks lokale transacties, elk publicerend van een gebeurtenis die de volgende triggert, met een compenserende actie voor elke stap om haar ongedaan te maken als een latere stap faalt. Sagas komen in twee smaken. Choreografie laat services op elkaars gebeurtenissen reageren, zonder centrale controller. Orkestratie laat een centrale coördinator de stappen aansturen, wat makkelijker is om over te redeneren en te bewaken. Sagas omarmen uiteindelijke consistentie: het systeem doorloopt tussentoestanden en convergeert dan. Ontwerp de gebruikerservaring en het auditspoor dus zo dat ze “in uitvoering” en “gecompenseerd” verantwoorden.

Behandel exactly-once als at-least-once plus ontdubbeling

Berichtenbrokers kunnen exactly-once-levering over falen heen niet echt garanderen. Wat zij en jij wel kunnen bereiken is at-least-once-levering met idempotente verwerking, wat exactly-once effecten oplevert. Ontwerp consumenten om dubbele berichten veilig af te handelen, met idempotentiesleutels of een log van verwerkte berichten. Ken de volgorde- en leveringsgaranties van je broker precies. Gebruik voor streaming consumentengroepen, partities en offsetbeheer met opzet, en maak herverwerking veilig, zodat je een stream na een bugfix kunt herhalen zonder downstream-toestand te corrumperen.

Instrumenteer gedistribueerde stromen van begin tot eind

Neem de drie pijlers van observeerbaarheid aan, gecorreleerd over servicegrenzen. Propageer een trace-/correlatie-ID door elke hop, zodat je één gebruikersverzoek kunt volgen over alle services die het raakt (gedistribueerde tracing). Zend gestructureerde statistieken uit (latentiepercentielen, foutpercentages, verzadiging, doorvoer) per service en per afhankelijkheid. Zend gestructureerde logs uit die de correlatie-ID dragen. Gebruik dit alles om service-level objectives te stellen en te alarmeren op symptomen die gebruikers werkelijk voelen, zoals foutpercentage en latentie, in plaats van alleen op de gezondheid van individuele machines. In een gedistribueerd systeem is observeerbaarheid geen optionele tooling. Het is de enige manier om gedrag onder gedeeltelijk falen te begrijpen.

Afwegingen: voor- en nadelen

TechniekVoordelenNadelen / kosten
Sterke consistentieEenvoudig mentaal model, geen verouderde leesactiesLagere beschikbaarheid tijdens partities, hogere latentie, coördinatiekosten
Uiteindelijke consistentieHoge beschikbaarheid, lage latentie, schaalbaarVerouderde leesacties, complex redeneren, conflictoplossing nodig
Herhalingen met backoffOverleeft tijdelijk falen automatischVersterkt belasting bij misbruik. Vraagt idempotentie en limieten
Circuit breakers / bulkheadsVoorkomen cascaderend falen, falen snelExtra complexiteit, afstemmen van drempels, risico van voortijdig activeren
Saga (tegenover 2PC)Schaalbaar, beschikbaar, geen gedistribueerde locksUiteindelijke consistentie, compensatielogica, moeilijker om over te redeneren

De hoofdafweging is die tussen coördinatie en onafhankelijkheid. Elke garantie die je over machines wilt (consistentie, volgorde, exactly-once) kost latentie, beschikbaarheid of complexiteit. Het vereist dat machines het eens worden, en overeenstemming over een onbetrouwbaar netwerk is duur. De vaardigheid is alleen de garanties te kopen die het bedrijf werkelijk nodig heeft, bewerking voor bewerking, en al het andere te ontwerpen voor gracieuze degradatie. Koop te veel consistentie en je systemen worden traag en broos. Koop te weinig en je krijgt stille datacorruptie die maanden later als auditfalen opduikt.

Vragen om met je team te bespreken

  1. Worden je veerkrachtpatronen geleverd als gedeelde platformstandaarden, of vindt elk team time-outs en herhalingen opnieuw uit? Het hoofdstuk behandelt idempotentie, time-outs, begrensde herhalingen, circuit breakers en tracing als het goedkoopst en meest betrouwbaar wanneer ze eenmaal in gedeelde bibliotheken en platformstandaarden zijn gebouwd. In een grote organisatie garandeert elk team ze met de hand laten bouwen inconsistentie: sommige paden herhalen niet-idempotente bewerkingen, sommige hebben geen time-out, sommige zenden geen correlatie-ID uit. Neem bewijs mee door een steekproef van services te auditen en te tellen hoeveel een expliciete time-out op elke externe aanroep zetten en een trace-ID van begin tot eind propageren. Als dat getal laag is, is de oplossing een platforminvestering, geen trainingsmemo. Standaardinstellingen maken veerkracht ook testbaar en controleerbaar, wat toezichthouders in financiën en overheid steeds vaker verwachten dat je aantoont.

  2. Componeren je time-outs en herhaalbudgetten over de hele aanroepketen, of herhaalt een diep verzoek zichzelf tot een storing? Een enkel verzoek doorkruist vaak veel hops, en als elke laag onafhankelijk drie keer herhaalt met haar eigen time-out, vermenigvuldigt het binnenste falen zich en wacht de buitenste aanroeper ver voorbij elke voor mensen te verdragen limiet. Stel een totaal tijdbudget voor het gebruikersgerichte verzoek vast en verdeel het langs de keten, zodat een binnenste service weet hoe weinig tijd ze nog heeft en snel faalt in plaats van in een storm te herhalen. Neem je afhankelijkheidsgraaf en een echte trace mee, tel dan de worstcase combinatie van time-out en herhaling op en vergelijk die met wat de gebruiker werkelijk zal wachten. Exponentiële backoff met jitter en een limiet op het totale aantal pogingen voorkomt dat een korte hapering een zelf toegebrachte denial of service wordt. Diepe, praatzieke synchrone ketens zijn hier de vijand, dus het antwoord kan je richting asynchrone stromen of minder hops duwen.

  3. Wanneer injecteerde je voor het laatst het falen dat je ontwerp zegt te overleven, en wat brak er dat je niet verwachtte? Veerkrachtpatronen zijn hypothesen tot je het systeem met opzet laat falen: een instantie doden, latentie aan een afhankelijkheid toevoegen, een deel van de berichten laten vallen, een batch twee keer opnieuw bezorgen. In een gedistribueerd systeem zijn de interessante falen gedeeltelijk en intermitterend, dus een circuit breaker of sagacompensatie die in code correct lijkt kan zich onder een echte time-out-die-misschien-voltooid-werd nog steeds misdragen. Neem de resultaten mee van een echte game day of falen-injectie-run, geen ontwerpdocument, en noteer welke alerts afgingen, hoe lang tracing nodig had om het falen te lokaliseren en of er een herhaalstorm ontstond. In gereguleerde sectoren is bewijs dat je falen hebt getest onderdeel van het aantonen van operationele veerkracht aan auditors. Als je er nog nooit een hebt gedaan, hoort het eerste experiment in een testomgeving met een strakke schadezone en een afbreekschakelaar.

  4. Kan het eigenaarsteam voor elke grote datastroom het consistentiemodel noemen dat ze biedt, en komt die keuze overeen met wat het bedrijf werkelijk nodig heeft? CAP en PACELC dwingen een bewuste keuze per bewerking af, maar in een grote organisatie is de standaard afdrijving: een stroom die uiteindelijk consistent begon voor een teller met lage inzet wordt hergebruikt voor iets wat nu betalingen goedkeurt of toegang verleent, en niemand herziet de garantie. De concurrerende overwegingen zijn echt, want sterke consistentie kost beschikbaarheid tijdens een partitie en latentie ook als er geen is, terwijl uiteindelijke consistentie snelheid koopt tegen de prijs van verouderde leesacties en conflictoplossing waarvoor je moet ontwerpen. Neem een catalogus van je belangrijkste datastromen mee, elk gelabeld met zijn huidige model (sterk, causaal, read-your-writes of uiteindelijk) en het zakelijke gevolg van een verouderde of verloren leesactie, en zoek dan naar mismatches waar de garantie sterker of zwakker is dan de inzet rechtvaardigt. In ondernemingsfinanciën en in uitkerings- of identiteitssystemen van de overheid is een uiteindelijk consistente leesactie achter een gezaghebbende beslissing het soort stil defect dat maanden later opduikt als auditbevinding of onterechte weigering, dus de review zelf is bewijs dat auditors zullen willen zien.

  5. Hoe gedragen je bedrijfstransacties over meerdere services zich halverwege, en wie is verantwoordelijk voor de compensaties die ze ontrafelen? Two-phase commit vervangen door sagas betekent dat het systeem zichtbare tussentoestanden doorloopt, en een stap kan slagen terwijl een latere stap faalt en een compenserende actie triggert die haar terugdraait. Voor een groot team roept dit moeilijke eigenaarschapsvragen op: de keten autoriseren-debiteren-crediteren-grootboek doorkruist vaak meerdere teams, en een compensatie die één team vergeet te implementeren laat geld of records blijvend inconsistent achter. Weeg choreografie, waar services op elkaars gebeurtenissen reageren zonder centrale controller en de stroom moeilijk te zien is, af tegen orkestratie, waar een coördinator de stappen aanstuurt en bewaakt ten koste van een component om te draaien. Neem het toestandsdiagram van je belangrijkste saga mee, de lijst met compenserende acties en hun eigenaren en bewijs dat “in uitvoering” en “gecompenseerd” worden afgehandeld in zowel de gebruikerservaring als het auditspoor. In bankieren en zaakbeheer in de publieke sector verwachten toezichthouders dat je precies kunt reconstrueren wat er gebeurde met een transactie die halverwege faalde, dus een niet-gemodelleerde tussentoestand is een compliancegat, niet alleen een bug.

  6. Overleven je berichtconsumenten dubbele en herordende levering, en kun je dat bewijzen voordat de broker de vraag afdwingt? Exactly-once-levering is een mythe, dus je echte garantie is at-least-once, en een consument die aanneemt dat elk bericht één keer en op volgorde aankomt zal dubbel verwerken op de dag dat de broker na een failover een batch opnieuw bezorgt. Over veel teams stapelt het risico zich op, omdat één niet-idempotente consument op een gedeelde stream downstream-toestand kan corrumperen waarvan andere teams afhangen, en het falen onzichtbaar is tot herhaling of een partitie gebeurtenissen herordent. De afweging is de engineeringkosten van idempotentiesleutels, een log van verwerkte berichten en expliciete offset- en partitiebehandeling, afgezet tegen de kosten van stille corruptie. Neem de lijst consumenten op je kritieke streams mee, noteer welke ontdubbelen en welke slechts hopen, en neem het resultaat mee van een echte herbezorgings- of herhalingstest in plaats van een verzekering dat het wel goed zit. Voor gegevensuitwisseling tussen overheidsinstanties en voor gebeurtenispipelines van ondernemingen is het vermogen een stream na een bugfix veilig te herhalen, zonder dubbele zaken of afschrijvingen te creëren, zowel een operationele noodzaak als iets wat auditors gedemonstreerd willen zien.

Sectorperspectief

Startup. Met twee of drie bewegende delen en geen platformteam weersta je het bouwen van gedistribueerde machinerie die je niet kunt bemannen. Koop veerkracht waar ze leeft in de SDK die je betaal- of berichtenleverancier al geeft, en besteed je schaarse aandacht aan de twee patronen die onomkeerbare schade voorkomen: een idempotentiesleutel op elke aanroep die geld verplaatst of een account wijzigt, en een time-out met begrensde herhaling zodat een onbetrouwbare verbinding nooit dubbel handelt. Houd het aantal netwerkhops klein, want elke synchrone afhankelijkheid die je toevoegt is een ding meer dat kan falen voordat je iemand met bereikbaarheidsdienst hebt om het op te merken.

Kleinbedrijf. Je hebt waarschijnlijk geen specialist in gedistribueerde systemen en een krap budget, dus behandel dit als kopen-niet-bouwen-vraag: geef de voorkeur aan beheerde wachtrijen, beheerde databases en platforms die herhalingen, volgorde en ontdubbeling voor je afhandelen in plaats van infrastructuur die je moet beheren. Formuleer je risico in gewone termen, wetend welke bewerkingen een klant zouden schaden als ze twee keer liepen of verouderde data teruggaven, en zet de idempotentie en at-least-once-functies aan die je leveranciers al bieden. Vermijd het aan elkaar knopen van services via een gedeelde database om een transactie na te bootsen, aangezien dat stilletjes het moeilijkste gedistribueerde probleem herschept zonder de tools om het te beheren.

Grote onderneming. Het kernprobleem is consistentie over veel teams, dus lever idempotentie, time-outs, begrensde herhalingen, circuit breakers en gecorreleerde tracing als gedeelde platformstandaarden in plaats van elke groep ze met de hand te laten bouwen. Standaardiseer hoe consistentiemodellen en leveringsgaranties per stroom worden gedeclareerd, houd regelmatig falen-injectie en game days en laat totale tijdbudgetten over diepe aanroepketens componeren zodat één service het platform niet in een storing kan herhalen. Beheer veerkracht als gemeten vermogen met service-level objectives op voor gebruikers zichtbare symptomen, want op jouw schaal kan één ontbrekende time-out uitgroeien tot een kopstoring.

Overheid. Systemen tussen instanties betekenen dat niemand het geheel bezit, dus ontwerp voor grenzen die je niet beheerst: duurzame wachtrijen met at-least-once-levering, ontdubbeling op een stabiele bericht-ID en correlatie-ID’s die over instantiegrenzen stromen om auditors een spoor van begin tot eind te geven. Aanbestedings- en transparantieregels duwen je het consistentiemodel en de leveringsgarantie van elke integratie te documenteren, en gezaghebbende beslissingen (identiteit, geschiktheid, uitkering) op sterk consistente leesacties te houden in plaats van gecachete endpoints. Behandel bewijs van getest falen en reconstrueerbare transactiegeschiedenis als opleveringen, aangezien operationele veerkracht en verantwoording aan het publiek contractuele en wettelijke verplichtingen zijn, geen interne beleefdheden.

Voorbeelden

Startup. Een kleine fintechstartup heeft slechts twee bewegende delen die over het netwerk praten: haar app en een externe betaalprovider. Zelfs op deze omvang laat ze elk afschrijvingsverzoek een idempotentiesleutel dragen en wikkelt ze de aanroep in een herhaling met backoff, zodat een verloren antwoord op een onbetrouwbare verbinding een klant nooit dubbel belast. Dit overslaan voelt op dag één goedkoop, maar de eerste dubbele afschrijving die een echte gebruiker raakt kost een supportbrand, een terugbetaling en een deuk in vertrouwen die het jonge bedrijf zich niet kan veroorloven.

Grote onderneming. Een wereldwijd ritdeelplatform verwerkt ritbetalingen via een saga: kaart autoriseren, passagier debiteren, chauffeur crediteren, grootboekpost vastleggen, elk een lokale transactie met een compenserende terugboeking. Elke stap draagt een idempotentiesleutel, zodat herhalingen na een netwerk-time-out nooit dubbel afschrijven. Aanroepen naar de fraudescoringservice zitten achter een circuit breaker. Wanneer die tijdens de piek degradeert, opent de breaker en vallen ritten terug op een conservatieve score in plaats van elke rit te blokkeren. Wanneer een klant een rit betwist, laat gedistribueerde tracing engineers hem in seconden over een dozijn services volgen.

Overheid. Een nationale identiteitsservice wordt door veel instanties gebruikt voor verificatie. Ze biedt een sterk consistente leesactie voor gezaghebbende statuscontroles (je mag geen uitkering goedkeuren op basis van verouderde identiteitsdata), plus een uiteindelijk consistent, gecachet endpoint voor opzoekingen met hoog volume en lage kritiek. Gegevensuitwisseling tussen instanties loopt over een duurzame berichtenwachtrij met at-least-once-levering, en de consument van elke instantie ontdubbelt op een bericht-ID, zodat een opnieuw bezorgd record geen dubbele zaak creëert. Correlatie-ID’s stromen over instantiegrenzen en geven auditors een spoor van begin tot eind van hoe de data van een burger tussen afdelingen bewoog.

Zakelijke onderbouwing: motivatie, ROI en TCO

Discipline in gedistribueerde systemen is goedkoop te kopen en de afwezigheid ervan wordt catastrofaal betaald. De invoeringskosten zijn engineeringtijd om idempotentie, time-outs, herhalingen, circuit breakers en tracing in gedeelde bibliotheken en platformstandaarden te bouwen. Dat is een bescheiden, grotendeels eenmalige investering die dan elk team ten goede komt. De kosten van niet aannemen worden gemeten in grote storingen: één ontbrekende time-out die uitgroeit tot een volledige platformstoring, een niet-idempotent betaalpad dat duizenden klanten dubbel belast of een gedistribueerde transactie zonder saga die data blijvend inconsistent achterlaat. Elk daarvan is een kopincident met directe omzet-, herstel- en reputatiekosten, en in gereguleerde sectoren boetes.

Formuleer de zaak voor het bestuur rond beschikbaarheid en schadezone. Veerkrachtpatronen verminderen direct zowel de frequentie als de duur van ernstige incidenten, de statistieken die bestuurders al volgen als uptime en gemiddelde hersteltijd. Gedistribueerde observeerbaarheid is de grootste hefboom op MTTR: teams met gecorreleerde tracing lossen incidenten over services op in een fractie van de tijd. Omdat deze vermogens het best als gedeelde platformstandaarden worden geleverd, zijn de marginale kosten per team laag en stapelt de opbrengst over de organisatie zich op. Het TCO-argument is eenvoudig: veerkracht van begin af aan inbouwen kost een fractie van het achteraf inbouwen na de storing die de kwestie afdwingt.

Antipatronen en valkuilen

  • Geen time-outs. Eén vastgelopen afhankelijkheid put elke thread uit en haalt het hele systeem neer.
  • Niet-idempotente bewerkingen herhalen. Dubbele bijwerkingen: dubbele afschrijvingen, dubbele records, dubbele e-mails.
  • Herhaalstormen. Gesynchroniseerde herhalingen zonder backoff en jitter die een kleine hapering versterken tot een storing.
  • Exactly-once-levering aannemen. Consumenten bouwen die breken op dubbele berichten die de broker uiteindelijk zal leveren.
  • Gedistribueerde transacties via gedeelde database. Services koppelen via één database om ACID na te bootsen, wat een gedistribueerde monoliet herschept.
  • Gedeeltelijk falen negeren. Code die aanneemt dat een externe aanroep volledig slaagt of volledig faalt, zonder afhandeling voor “in time-out gelopen maar misschien voltooid”.
  • Geen correlatie-ID’s. Een incident over services debuggen door ongerelateerde logs op tien machines te greppen.
  • Praatzieke synchrone aanroepketens. Diepe synchrone afhankelijkheidsgrafen waar elke trage hop het hele verzoek stalt.

Volwassenheidsmodel

  • Niveau 1: Initiëren. Externe aanroepen worden behandeld als lokale aanroepen. Time-outs ontbreken of zijn naïef, herhalingen zijn afwezig of roekeloos en falen cascaderen door het systeem. Er is geen gedeeld beeld van consistentie of levering, en een incident over services debuggen betekent achteraf logs per machine uitpluizen.
  • Niveau 2: Ontwikkelen. Sommige teams voegen time-outs en basale herhalingen en een beetje idempotentie toe, maar de praktijken zijn inconsistent van service tot service. Logs zijn gecentraliseerd maar niet gecorreleerd, dus een verzoek over hops traceren is handwerk. Gedistribueerde transacties worden gehoopt te werken in plaats van gemodelleerd, en consistentiegaranties leven in de hoofden van individuele engineers.
  • Niveau 3: Standaardiseren. Idempotentie, begrensde herhalingen, backoff met jitter, circuit breakers en bulkheads zijn standaard in de organisatie via gedeelde bibliotheken. Sagas met compenserende acties handelen transacties over meerdere services af, gedistribueerde tracing met correlatie-ID’s is aanwezig en elke grote datastroom documenteert haar consistentiemodel en leveringsgarantie. De regels zijn opgeschreven en organisatiebreed gehandhaafd in plaats van aan elk team overgelaten.
  • Niveau 4: Beheersen. Veerkracht wordt gemeten aan de hand van uitgangswaarden, niet alleen aanwezig. Je volgt foutpercentage, latentiepercentielen, verzadiging en doorvoer per service en afhankelijkheid, let op herhaalverhoudingen en open-percentages van circuit breakers en stelt service-level objectives op voor zichtbare symptomen. Totale tijdbudgetten worden geverifieerd om over aanroepketens te componeren, gemiddelde hersteltijd voor incidenten over services is een bewaakte statistiek, en resultaten van falen-injectie en game days voeden de cijfers die elke wijziging poorten.
  • Niveau 5: Orkestreren. Veerkracht is de continu verbeterde platformstandaard, geïntegreerd over de hele organisatie en adaptief aan omstandigheden. Falen-injectie draait routinematig in productie met strakke schadezones, systemen degraderen gracieus door ontwerp, en consistentie- en leveringskeuzes worden herzien naarmate belasting en zakelijke inzet verschuiven. De statistieken van niveau 4 sturen geautomatiseerde reacties en gestage architectonische evolutie aan, zodat het gedistribueerde landschap met elk incident robuuster wordt in plaats van het slechts te overleven.

Ideeën voor discussie

  1. Welke van je kritieke bewerkingen zijn vandaag werkelijk idempotent, en welke stilletjes niet?
  2. Kan je team voor elke grote datastroom het consistentiemodel en de leveringsgarantie uit het hoofd noemen?
  3. Waar zou een circuit breaker je laatste cascaderende storing hebben voorkomen?
  4. Hoe lang duurt het nu om één falend verzoek te traceren over alle services die het raakt?
  5. Welke van je “gedistribueerde transacties” leunen eigenlijk op geluk, en welke zijn echte sagas met compensaties?
  6. Als je berichtenbroker een uur lang elk bericht twee keer opnieuw bezorgde, wat zou er breken?

Belangrijkste inzichten

  • Neem aan dat het netwerk onbetrouwbaar is en falen gedeeltelijk. Ontwerp elke externe interactie voor traagheid, verlies, duplicatie en herordening.
  • Besluit consistentie tegenover beschikbaarheid per bewerking met CAP/PACELC en documenteer het model dat elke stroom biedt.
  • Idempotentie, time-outs, begrensde herhalingen en backoff met jitter zijn één pakket. Neem herhalingen nooit aan zonder de andere drie.
  • Circuit breakers en bulkheads beperken falen. Sagas met compensaties vervangen onwerkbare gedistribueerde transacties.
  • Behandel levering als at-least-once en maak verwerking idempotent om exactly-once effecten te bereiken.
  • Gecorreleerde tracing, statistieken en logs zijn de enige manier om gedistribueerde stromen te begrijpen en te beheren.

Referenties en verder lezen

  • Martin Kleppmann, Designing Data-Intensive Applications
  • Andrew Tanenbaum and Maarten van Steen, Distributed Systems: Principles and Paradigms
  • Michael Nygard, Release It!: Design and Deploy Production-Ready Software
  • Sam Newman, Building Microservices
  • Chris Richardson, Microservices Patterns (sagas, transactional messaging)
  • Eric Brewer, “CAP Twelve Years Later” and Daniel Abadi on PACELC
  • Leslie Lamport, “Time, Clocks, and the Ordering of Events in a Distributed System”
  • Cindy Sridharan, Distributed Systems Observability
  • Nassim Nicholas Taleb’s notion of antifragility (as applied by resilience-engineering literature)