De Drie Foutconcepten Die Je Moet Begrijpen
Welkom
Gebalanceerde systemen falen in patronen. Zodra je de patronen kent, wordt elke postmortem een herkenningsoefening in plaats van een raadsel.
Drie concepten dekken het merendeel van wat er in de productiefase van belang is bij het analyseren van fouten:
Enige punt van fout (SPOF): een component wiens falen leidt tot een uitval van een groter systeem. Vaak verborgen: de DNS-server op wie iedereen aangewezen is; het certificaat waaraan alles vernieuwd wordt; de enige primaire database.
Kettingfout: het falen van een component activeert een ander, wat op zijn beurt een ander activeert. Een traag database veroorzaakt time-outs in de API-laag, wat retries veroorzaakt, wat de belasting van het database verder verhoogt, wat meer time-outs veroorzaakt. De explosie verspreidt zich.
Explosieradius: hoeveel van het systeem uitvalt wanneer een stukje falen. Architecturale keuzes binden of onbinden de radius. Een SPOF heeft een ongebonden radius. Een bulkgehaakte service heeft een gebonden radius.
Na het volgen van deze les zul je:
- SPOFs in een architectuur identificeren door inspectie
- Kettingfout patronen herkennen: donderende kudde, retry-storm, wachtrij van de dood
- Een echte tijdlijn lezen en de trigger scheiden van de verborgen fout die de trigger aan de oppervlakte bracht
- Schuldloze actiepunten schrijven die de systemen raken in plaats van mensen, met preventie / detectie / herstel
- Over bulkheads & circuitbreakers redeneren als explosieradius-begrenzende instrumenten
Spot de Enige Punt van Fout
Laag-op-laag Architectuurinspectie
Overweeg een klein webarchitectuur:
- DNS: api.example.com -> enkel IP-adres van nameserver 203.0.113.10 gehost door één DNS-provider
- CDN: enkele CDN-leverancier voor api.example.com
- Ingress: twee reverse proxy-machines achter een laderbalancer
- Backend: zes API-replica's in twee beschikbaarheidszones (drie per zone)
- Database: één primaire + één leesslave, in dezelfde beschikbaarheidszone
- Cache: Redis-cluster, drie knopen verspreid over dezelfde twee beschikbaarheidszones
Vraag: welke componenten zijn SPOFs? Tip: SPOFs zijn niet altijd de duidelijk 'enkele machine'-soort. Een cluster van drie machines die allemaal in dezelfde beschikbaarheidszone staan, is een SPOF voor het falen van die zone.
Drie Klassieke Cascade Patronen
Fouten Reizen Door Afhankelijkheden
Patroon 1: Donderend horden. Een gedeelde bron (cache, sleutel, database) faalt of herstart. Elke klant die ervop afhankelijk was, probeert opnieuw. De overstroming overweldigt wat opnieuw opstart; de herhaalpogingen stapelen zich op sneller dan de herstelling het kan opnemen; de herstelling gaat nooit door.
Patroon 2: Herhaalstorm. Een downstream service vertraagt. Bovendien herstellen de opdrachtgevers in plaats van te falen. De herhaalpogingen vermenigvuldigen de oorspronkelijke belasting. De vertraagde service vertraagt verder, waardoor meer herhaalpogingen worden getriggerd. Uiteindelijk overschrijdt de belasting zelfs een gezonde versie van de service.
Patroon 3: Doodse wachtrij. Een verwerkingswachtrij met geen backpressure ontvangt sneller dan het verwerkt. De wachtrij groeit oneindig. Geheugen uitgeput; de consument crasht; herstart; vindt een nog grotere wachtrij; crasht opnieuw.
Gemeenschappelijke draad: een kleine aanvankelijke verstoring treedt een positieve terugkoppelingsslag aan. Het systeem eigen reactie versterkt de fout in plaats van het te dempen.
Dempende Mechanismen
Exponentieel teruglopen met ruis. Klanten die opnieuw wachten, wachten langer elke keer, met willekeurige afwijking. Voorkomt gesynchroniseerde herhaalgolven.
Circuit breaker. Een opdrachtgever volgt de foutenrate van downstream. Na een drempelwaarde stopt de opdrachtgever met het bellen voor een afkoelingsperiode & faalt onmiddellijk zijn eigen verzoeken in plaats daarvan. Voorkomt nutteloos werk, laat downstream herstellen.
Bulkhead. Isolatie van bronnen per afhankelijkheid. Verbindingspool A voor database, aparte verbindingspool B voor cache. Een trage database kan geen enkele connectie verhongeren; cache oproepen blijven doorgaan.
Belastingvermindering. Wanneer overbelast, laten ze verzoeken aan de rand vallen in plaats van ze aan te nemen & langzaam te falen. Een 429 in 1 ms is beter dan een 500 in 30 seconden.
Terugdrukking. Langzame producenten wanneer consumenten niet kunnen bijhouden. Wachtrijen worden gebonden; verzenders blokkeren; de oorspronkelijke bron van werk voelt de weerstand.
Diagnose een Cascade
Een teams API-laag gaat kapot tijdens een routineuze database failover. Tijdbalk:
- 14:00:00 — operator promoot de standby database. Voorziene onbereikbaarheid: ~10 seconden.
- 14:00:08 — primaire onbereikbaar. API-laag begint met het falen van verzoeken met databaseverbindingfouten.
- 14:00:08 — API-laag herhaalt (standaardconfiguratie: 5 herhalingspogingen, geen backoff, 100 milliseconden uit elkaar).
- 14:00:11 — standby wordt gepromoteerd, accepteert nieuwe verbindingen.
- 14:00:11 — API-laag opent duizenden nieuwe databaseverbindingen tegelijkertijd (elke replica × elke gelijktijdige verzoek × elke herhaalpoging).
- 14:00:13 — nieuwe primaire's verbindingspool is uitgeput; nieuwe verbindingen worden afgewezen.
- 14:00:13-14:05:00 — API-laag replicas uitputten verbindingspools, gooien uitzonderingen, crashen, herstarten, herhalen.
- 14:05:00 — operator stopt manueel API-laagverkeer; database stabiliseert.
- 14:10:00 — geleidelijke verkeersherstel voltooid. Totaal uitval: ~10 minuten (in plaats van het verwachte ~10 seconden).
DNS SERVFAIL: Twee Samenkoppelende Defecten
Een Echte-Vorm Postmortem
Wat volgt is een gezuiverde versie van een reëel incident. Merknamen veranderd, IPs geanonimiseerd; de vorm, de tijdbalk en de lessen zijn echt.
Samenvatting
Site example.com gaf SERVFAIL op vanuit alle openbare DNS-resolvers voor ongeveer 3-4 uur. Alle andere 46 zones op dezelfde DNS-master waren ongemoeid. Oorzaak: twee samenkoppelende defecten.
1. Vendor A (een secundaire DNS-leverancier) voegde een nieuwe interne sync IP toe die niet in de primaire's allow-axfr-ips toegangslijst stond.
2. De example.com zone had een jarenoude RFC-schendende CNAME-conflict (demo.example.com had zowel CNAME- als MX/TXT-records op hetzelfde label) wat bij Vendor A de zone weigerde op verse AXFR.
Tijdbalk (UTC)
- ~15:00 — Vendor A voegt nieuwe sync IP 198.51.100.42 toe aan hun infrastructuur
- 15:02 — first AXFR-out denied voor 198.51.100.42 verschijnt in primaire DNS-logboeken (geen waarschuwing op deze signaal)
- ~18:00 — SOA verloopvenster bereikt; Vendor A verwijderen example.com zone uit cache
- ~18:30 — SERVFAIL gedetecteerd extern
- ~19:45 — oorzaak geïdentificeerd
- 20:00 — 198.51.100.42 toegevoegd aan allow-axfr-ips; primaire herstart
- 20:05 — NOTIFY verstuurd; AXFR geïnitieerd; zone HEEFT NOG STEEDS SERVFAIL (CNAME-conflict)
- 20:07 — check-zone onthult 1 fout: CNAME-conflict op demo.example.com
- 20:09 — CNAME vervangen met A-record; zonecontrole schoon (0 fouten)
- 20:10 — NOTIFY verstuurd; AXFR voltooid; Vendor A begint zone te serveren
- 20:11 — dig @8.8.8.8 example.com A retourneert juiste IP — OPGELOST
Waarom alleen example.com?
Alle 47 zones delen hetzelfde DNS-primair. De AXFR-IP-blok die alle zones beïnvloedde. Maar alleen example.com had de CNAME-conflict en had alleen example.com een nieuwe AXFR nodig op het moment dat de toestemming werd toegepast. Andere zones hadden al geüpdatet voordat de toestemming of hadden nog niet hoeven te updaten.
Latente defect
Het CNAME-conflict op demo.example.com bestond al jaren. Het werkte omdat het primaire de zone vanuit zijn database diende (soepel over RFC-overschrijdingen) en Vendor A diende van oude gecachte data van voor de inbreuk werd geïntroduceerd. Toen Vendor A zijn cache verliet en nieuwere gegevens nodig had, kwam de inbreuk aan het licht.
Trigger
Vendor A voegde stilzwijend een nieuw synchronisatie-IP toe. De primaire's toegestane lijst bevatte het niet. AXFR geweigerd. Drie uur later (SOA verlopen), verwijderde Vendor A de zone. De latente defecten kwamen aan het licht toen het systeem probeerde te herstellen.
Schrijf schuldloze actiepunten
Schuldloos: Doel op systemen, niet op mensen
Een schuldloos actiepunt noemt iets dat de systeem anders moet doen, niet iets dat een persoon anders moet doen. 'Opleiden van de operator' is schadelijk. 'Voeg een geautomatiseerde controle toe die dit vóór de implementatie opsporent' is schuldloos.
Goede schuldloze actiepunten groeperen zich in drie dimensies:
- Preventie: maak het slechte iets moeilijker of onmogelijk
- Detectie: merkt het eerder op als het gebeurt
- Herstel: beperk de schade als het gebeurt
Elk item moet (1) de specifieke systeemwijziging, (2) het eigen team noemen en (3) de dimensie die het dient.
Kamers die Zinken zonder het Schip
Overgenomen van Scheepsbouw
Schepen hebben waterdichte wanden: verticale wanden die de romp in compartimenten verdelen. Een compartiment kan overstromen zonder dat het schip zinkt; een ander kan falen zonder invloed op de rest.
Gebruikte systemen lenen hetzelfde woord & dezelfde idee.
Bulkhoofdpatron: isoleren van resources per afhankelijkheid. Een service die drie downstream-API's aanroept, gebruikt drie aparte connection pools, drie aparte thread pools, drie aparte herstelpatronen. Een trage of falende downstream kan de resources van de andere twee niet gebruiken.
Zonder bulkhoofden: één trage afhankelijkheid verbruikt het gedeelde thread pool; aanroepen naar andere afhankelijkheden blokkeren wachtend op threads; het hele service wordt onresponsief.
Met bulkhoofden: één trage afhankelijkheid verbruikt haar eigen pool; aanroepen naar haar falen snel; aanroepen naar andere afhankelijkheden gaan normaal door; de sloopstraal blijft beperkt tot de falende afhankelijkheid.
Stroombrekerpatron
Stroombrekerpatron: een stateful wrapper rond een downstream-afhankelijkheid die fouten frequentie bijhoudt. Drie staten:
- Gesloten (normaal): aanroepen gaan door. Fouten geteld.
- Open (uitgetrokken): na een foutdrempel (bijvoorbeeld, 50% fouten in de laatste 30 seconden), gaat de breker open. Aanroepen falen meteen zonder het dependency te proberen. Bespaart de aanroeper van nutteloze inspanning; bespaart de dependency van belasting terwijl het ongezond is.
- Half-open (testen): na een afkoelingsperiode, laat de breker een kleine fractie van aanroepen door. Als ze slagen, sluit het weer normaal. Als ze falen, opent het weer voor een andere afkoeling.
Het sleutelidee: de stroombreker voorkomt nutteloze inspanning tijdens bekende ongezonde perioden, & geeft de downstream een kans om te herstellen zonder voortgezette belasting.
Bulkhoofden beperken de sloopstraal. Stroombrekers voorkomen dat de sloop zichzelf voortzet.
Beperk de Sloopstraal
Je API-service-service maakt gebruik van vier downstream services: User Service, Recommendation Service, Notification Service & een derde partij Payment API. Het team heeft gehoord dat de 'Recommendation Service een beetje onbetrouwbaar' is en wil ervoor zorgen dat de rest van het systeem gezond blijft als het faalt.
Vandaag maakt de service gebruik van een enkele gedeelde thread pool van 200 threads en een enkele gedeelde HTTP-verbinding pool. De vier downstreams concurreren om deze resources. Er zijn geen circuitbreakers.
Ontwerp een Falenmode Review
Synthese
Je hebt geleerd SPOFs te herkennen door inspectie, patronen van cascaderende falen te herkennen, een postmortem productief te lezen, schuldloze actiepunten te schrijven voor preventie, detectie en herstel, en de inslagvlak te binden met bulkheads + circuitbreakers + graceful degradation.
Gebruik alle vijf.
Je team lanceert een nieuwe service search.example.com die afhankelijk is van drie downstream services: een primaire zoekindex (index.example.com), een analytische service (analytics.example.com) & een aanbevelingen service (recs.example.com). Het team wil dat je een 'falenmode review' leidt voordat de lancering.
Waar Dit Cursus Volgende Gaat
Waar Dit Cursus Volgende Gaat
Je kunt nu een SPOF herkennen, een cascade herkennen, een postmortem productief lezen, schuldloze actiepunten schrijven en de inslagvlak binden door ontwerp.
De laatste les in deze cursus (cs_distsys_observability_and_capacity) onderwijst wat je moet meten om te ontdekken dat een probleem zich voordoet voordat gebruikers dat merken. Gezondheidcontroles, versie-eindpunten, de vier gouden signalen op proxylaag en hoe beslissingen over overcapaciteit terug te voeren zijn op geobserveerde data.
Bijles: geometry_of_failure_modes_and_blast_radius beoogt tussenstandencentraliteit (welke grafiekknop is de bottleneck) & min-cut (de bovengrens van de blaststraal) te begrijpen.
Goed gedaan. Verder.