Die drei Fehlertoleranzkonzepte, die man kennen sollte
Willkommen
Verteilte Systeme versagen in Mustern. Sobald man die Muster kennt, wird jeder Post-Mortem ein Erkennungsexercise anstelle eines Rätsels.
Drei Konzepte decken den meisten, was in der Fehleranalyse von laufenden Systemen wichtig ist:
Einziger Fehlerpunkt (SPOF): Ein Komponente, deren Ausfall ein größeres System lahmlegt. Oft versteckt: Der DNS-Server, auf den alle angewiesen sind; das Zertifikat, gegen das alles erneuert wird; der einzige Datenbankmaster.
Kaskadierender Ausfall: Ein Komponente versagt und löst den Ausfall einer anderen aus, die wiederum einen weiteren auslöst. Eine langsame Datenbank verursacht Timeouts im API-Schicht, was zu Wiederholungsversuchen führt, was die Datenbank weiter belastet, was zu weiteren Timeouts führt. Die Explosion breitet sich aus.
Explosionsradius: Wie viel des Systems ausfällt, wenn eine Komponente versagt. Architekturentscheidungen binden entweder den Radius oder lassen ihn ungebunden. Ein SPOF hat ungebundenen Explosionsradius. Ein bulkhead-geschütztes Service hat einen begrenzten Radius.
Bis Ende dieses Unterrichts wirst du:
- SPOFs in einer Architektur erkennen, indem du sie untersuchst
- Kaskadierende Fehlersituationen erkennen: Donnernder Sturm, Wiederholungssturm, Warteschlange des Todes
- Einen realen Zeitstrahl lesen und den Auslöser vom latenten Defekt trennen, der vom Auslöser aufgedeckt wurde
- Schuldlose Maßnahmen erstellen, die sich auf Systeme und nicht auf Menschen konzentrieren, und decken Prävention, Erkennung und Wiederherstellung ab
- Über Bulkheads & Schaltschlusseinrichtungen als Instrumente zur Begrenzung des Explosionsradius nachdenken
Entdecke den Einzigen Fehlerpunkt
Untersuchung einer schichtenbasierten Architektur
Überlege dir eine kleine Webarchitektur:
- DNS: api.example.com -> IP-Adresse des einzigen Nameservers 203.0.113.10, der von einem einzelnen DNS-Anbieter gehostet wird
- CDN: Ein einzelner CDN-Anbieter vor api.example.com
- Ingress: Zwei Reverse-Proxy-Computer hinter einem Lastausgleichsgerät
- Backend: Sechs API-Instanzen in zwei Verfügbarkeitszonen (drei pro Zone)
- Datenbank: Eine Primär- und eine Lesedatenbank in derselben Verfügbarkeitszone
- Cache: Redis-Cluster, drei Node verteilt auf dieselben beiden Verfügbarkeitszonen
Frage: Welche Komponenten sind SPOFs? Hinweis: SPOFs sind nicht immer die offensichtlichen 'einzigen Maschinen'-Art. Eine Cluster von drei Maschinen, die sich alle in einer Verfügbarkeitszone befinden, ist ein SPOF für den Ausfall der Zone.
Drei klassische Kaskadenmuster
Versager reisen durch Abhängigkeiten
Muster 1: Donnernder Sturm. Ein gemeinsames Ressource (Cache, Sperre, Datenbank) schlägt oder startet neu. Jeder Kunde, der darauf angewiesen war, versucht erneut gleichzeitig. Die Flut überwältigt, was wieder aufgebaut wird; Die Wiederholungen überlagern sich schneller als die Wiederherstellung sie absorbieren kann; Die Wiederherstellung kommt nie zustande.
Muster 2: Wiederholungssturm. Eine downstream-Dienst verlangsamt sich. Oberflächliche Anrufer versuchen anstatt zu scheitern, es erneut. Die Wiederholungen multiplizieren die ursprüngliche Belastung. Der Dienst verlangsamt sich weiter, was mehr Wiederholungen auslöst. Schließlich übersteigt die Belastung selbst eine gesunde Version des Dienstes.
Muster 3: Warteschlange des Todes. Eine Verarbeitungs-Warteschlange mit keiner Rückdruckkraft erhält schneller als sie verarbeitet. Die Warteschlange wächst unbegrenzt. Der Speicher wird erschöpft; der Verbraucher stürzt ab; startet neu; findet eine immer größere Warteschlange; stürzt erneut ab.
Gemeinsamer Nenner: Eine kleine ursprüngliche Störung löst einen positiv rückkopplenden Schleifen aus. Die Systemantwort verstärkt das Versagen anstelle der Dämpfung.
Dämpfungsmechanismen
Exponentielle Verzögerung mit Störgeräuschen. Wiederholende Clients warten länger, jedes Mal mit zufälligem Versatz. Verhindert synchronisierte Wiederholungswellen.
Schaltersicherung. Ein Anrufer verfolgt die Versagerate des downstreams. Jenseits eines Schwellenwerts stoppt der Anrufer das Anrufen für einen Abkühlungszeitraum und versagt sofort seine eigenen Anfragen.
Ballastkammer. Ressourcen isolieren pro Abhängigkeit. Verbindungspool A für Datenbank, separater Verbindungspool B für Cache. Eine langsame Datenbank kann keine Verbindungen hungern; Cache-Anrufe werden fortgesetzt.
Lastabschaltung. Wenn überlastet, werden Anfragen am Rand abgelehnt anstatt akzeptiert und langsam zu scheitern. Eine 429 in 1 ms ist besser als eine 500 in 30 Sekunden.
Rückdruck. Langsame Produzenten, wenn Konsumenten nicht weiterkommen. Queues werden begrenzt; Sender blockieren; die ursprüngliche Quelle der Arbeit spürt die Reibung.
Diagnose einer Kaskade
Ein Teams-API-Tier schmilzt während einer standardmäßigen Datenbank-Weiterleitung. Zeitplan:
- 14:00:00 — Betreuer befördern die stehende Datenbank. Erwartete Nichtverfügbarkeit: ~ 10 Sekunden.
- 14:00:08 — Primärdienst nicht verfügbar. API-Tier-Fehler mit Datenbankverbindungsfehlern beginnen.
- 14:00:08 — API-Tier versucht erneut (Standardkonfiguration: 5 Wiederholungen, kein Zurückhaltungszeitraum, 100 ms Trennzeit).
- 14:00:11 — Standleitung wird befördert und nimmt neue Verbindungen entgegen.
- 14:00:11 — API-Tier öffnet gleichzeitig Tausende neuer Datenbankverbindungen (jedes Replica × jeder laufende Antrag × jede Wiederholung).
- 14:00:13 — Die Verbindungsstapel der neuen Primärdatenbank sind ausgeschöpft; neue Verbindungen werden abgelehnt.
- 14:00:13-14:05:00 — Die Replicas des API-Tiers erschöpfen die Verbindungsstapel, werfen Ausnahmen, stürzen ab, starten erneut, wiederholen.
- 14:05:00 — Betreuer stoppen den API-Tier-Betrieb manuell; Datenbank stabilisiert sich.
- 14:10:00 — allmähliche Wiederherstellung des Verkehrs ist abgeschlossen. Gesamte Ausfallzeit: ~ 10 Minuten (im Gegensatz zu der erwarteten ~ 10 Sekunden).
DNS SERVFAIL: Zwei kumulative Mängel
Eine echte Form eines Postmortems
Was folgt, ist eine desinfizierte Version eines echten Vorfalls. Die Namen der Anbieter wurden geändert, IPs anonymisiert; die Form, die Zeitleiste und die Lehren sind echt.
Zusammenfassung
Die Website example.com gab SERVFAIL von allen öffentlichen DNS-Resolvern für etwa 3-4 Stunden zurück. Alle anderen 46 Zonen auf demselben DNS-Master waren nicht betroffen. Ursache: zwei kumulative Mängel.
1. Anbieter A (ein sekundäres DNS-Anbieter) fügte eine neue interne Synchron-IP hinzu, die nicht in der allow-axfr-ips-Zulassungsliste der Primärdatenbank enthalten war.
2. Die example.com-Zone hatte einen seit Jahren bestehenden RFC-verletzenden CNAME-Konflikt (demo.example.com hatte sowohl CNAME- als auch MX/TXT-Records auf demselben Label), der es Anbieter A verwehrte, die Zone auf frische AXFR zu akzeptieren.
Zeitleiste (UTC)
- ~15:00 — Anbieter A fügt die neue Synchron-IP 198.51.100.42 in ihre Infrastruktur hinzu
- 15:02 — erster AXFR-out denied für 198.51.100.42 erscheint in den Logs des primären DNS (keine Warnung auf diesem Signal)
- ~18:00 — SOA-Ablaufzeitraum erreicht; Vendor A löscht die example.com-Zone aus dem Cache
- ~18:30 — externes SERVFAIL festgestellt
- ~19:45 — Ursache identifiziert
- 20:00 — 198.51.100.42 wird der Liste allow-axfr-ips hinzugefügt; primäres System neu gestartet
- 20:05 — NOTIFY gesendet; AXFR initiiert; Zone IST immer noch SERVFAIL (CNAME-Konflikt)
- 20:07 — check-zone zeigt 1 Fehler: CNAME-Konflikt auf demo.example.com
- 20:09 — CNAME wird durch A-Record ersetzt; Zone-Überprüfung sauber (0 Fehler)
- 20:10 — NOTIFY gesendet; AXFR abgeschlossen; Vendor A beginnt, die Zone zu veröffentlichen
- 20:11 — dig @8.8.8.8 example.com A gibt korrekt IP aus — BEENDET
Warum nur example.com?
Alle 47 Zonen teilen sich das gleiche DNS-primäre. Die AXFR-IP-Block betraf alle Zonen. Aber nur example.com hatte den CNAME-Konflikt und benötigte nur eine frische AXFR, als der Verweigerungszustand durchgesetzt wurde. Andere Zonen hatten sich bereits aktualisiert, bevor der Verweigerungszustand oder noch nicht benötigt.
Versteckter Defekt
Der CNAME-Konflikt auf demo.example.com bestand seit Jahren. Er funktionierte, weil das primäre System die Zone aus seiner Datenbank (lasiv gegenüber RFC-Verstößen) ausging und Vendor A die Daten von veralteten gecacheten Daten vor dem Einführung des Verstoßes veröffentlichte. Als Vendor A seinen Cache fallen ließ und frische Daten benötigte, kam der Verstoß ans Licht.
Auslöser
Vendor A fügte einen neuen Synchronisierungs-IP hinzu. Die Allowliste des primären Systems enthielt sie nicht. AXFR wurde verweigert. Drei Stunden später (SOA-Ablauf) löschte Vendor A die Zone. Der versteckte Defekt wurde sichtbar, als das System versuchte, sich zu erholen.
Schreiben von schuldunabhängigen Maßnahmen
Schuldunabhängig: Ziel sind Systeme, nicht Menschen
Ein schuldunabhängiger Maßnahmenpunkt nennt etwas, das das System anders machen sollte, nicht etwas, das eine Person anders machen sollte. 'Ausbildung des Betreibers' ist verantwortlich. 'Fügen Sie eine automatisierte Überprüfung hinzu, die dies vor der Bereitstellung erkennt' ist schuldunabhängig.
Gute schuldunabhängige Maßnahmenpunkte bilden sich in drei Dimensionen:
- Prävention: Mach das Schlechte schwerer oder unmöglich
- Erkennung: Merke es früher, wenn es passiert
- Wiedergutmachung: Begrenze die Schäden, wenn es passiert
Jeder Punkt sollte (1) die spezifische Systemänderung, (2) die verantwortliche Abteilung und (3) die Dimension, der er dient, nennen.
Kammern, die ohne das Schiff versinken
Entlehen von Schiffbau-Technik
Schiffe tragen wasserdichte Trennwände: vertikale Wände, die den Rumpf in Kammern teilen. Eine Kammer kann überflutet werden ohne das Schiff zu sinken; eine andere kann versagen ohne die anderen zu beeinflussen.
Verteilte Systeme leihen den gleichen Begriff & die gleiche Idee.
Trennwandsmuster: Ressourcen pro Abhängigkeit isolieren. Ein Service, der drei downstream-APIs aufruft, verwendet drei separate Verbindungs-Pools, drei separate Thread-Pools, drei separate Wiederherstellungsbudgets. Ein langsames oder versagendes downstream kann die für die anderen beiden zugewiesenen Ressourcen nicht verbrauchen.
Ohne Trenwände: Eine langsame Abhängigkeit verbraucht den gemeinsamen Thread-Pool; Aufrufe an andere Abhängigkeiten blockieren, bis Threads verfügbar sind; das gesamte Service wird unansprechbar.
Mit Trenwänden: Eine langsame Abhängigkeit verbraucht ihren eigenen Pool; Aufrufe an sie schließen schnell; Aufrufe an andere Abhängigkeiten laufen weiterhin normal; der Explosionsschutz bleibt auf die versagende Abhängigkeit beschränkt.
Schaltkreis-Brecher
Schaltkreis-Brecher-Muster: Ein um einen downstream-Abhängigkeit herum befindlicher, Zustandsbewusster Wrapper, der Fehlerraten verfolgt. Drei Zustände:
- Geschlossen (normal): Anrufe werden weitergeleitet. Fehlschläge werden gezählt.
- Geöffnet (ausgelöst): Ist ein Fehler-Schwellenwert überschritten (z.B. 50% Fehlschläge in den letzten 30 Sekunden), öffnet der Brecher. Anrufe schließen sofort ohne die Abhängigkeit zu versuchen. Spart den Aufrufer vor der vergeudeten Arbeit; spart die Abhängigkeit vor der Belastung während sie ungesund ist.
- Halb geöffnet (Testen): Nach einer Abkühlungszeit lässt der Brecher einen kleinen Teil der Anrufe zu. Wenn sie erfolgreich sind, schließt er zurück zum Normalzustand. Wenn sie fehlschlagen, öffnet er erneut für eine weitere Abkühlungszeit.
Das Schlüsseleinsicht: Der Schaltkreis-Brecher verhindert vergeudete Anstrengungen während bekannt-ungesunder Perioden & gibt der downstream-Chance zu sich selbst zu erholen ohne fortgesetzte Belastung.
Trenwände begrenzen den Explosionsschutz. Schaltkreis-Brecher verhindern, dass der Blast sich selbst erhält.
Den Explosionsschutz begrenzen
Ihre API-Dienststelle ruft vier downstream-Dienste auf: User Service, Empfehlungsdienst, Benachrichtigungs-Dienst und einen dritten Payment-API-Anbieter. Das Team hat gehört, dass der Empfehlungsdienst 'ein bisschen flüchtig' war, und möchte sicherstellen, dass das System, wenn es versagt, gesund bleibt.
Heutzutage verwendet der Dienst einen einzigen geteilten Pool von 200 Threads und einen einzigen geteilten HTTP-Verbindungs-Pool. Die vier downstreams konkurrieren um diese Ressourcen. Es gibt keine Schaltkreisbrecher.
Entwerfen Sie eine Fehlermodus-Übersicht
Synthese
Sie haben gelernt, SPOFs durch Inspektion zu erkennen, kaskadierende Versagensmuster zu erkennen, den Auslöser von latenter Defekt in einer Postmortem zu unterscheiden, verantwortungsbewusste Maßnahmen über Prävention, Erkennung und Wiedergutmachung zu verfassen und den Wirkungsbereich mit Bulkheads, Schaltkreisbrechern und sanfter Degradation zu begrenzen.
Anwenden Sie alle fünf.
Ihr Team startet einen neuen Dienst unter search.example.com, der auf drei downstream-Dienste angewiesen ist: einen primären Suchindex (index.example.com), einen Analyse-Dienst (analytics.example.com) und einen Empfehlungsdienst (recs.example.com). Das Team möchte, dass Sie eine 'Fehlermodus-Übersicht' vor der Veröffentlichung durchführen.
Wohin sich dieser Kurs in Zukunft entwickelt
Wohin sich dieser Kurs in Zukunft entwickelt
Sie können jetzt einen SPOF erkennen, einen Cascade erkennen, eine Postmortem produktiv lesen, verantwortungsbewusste Maßnahmen verfassen und den Wirkungsbereich durch Entwurf begrenzen.
Die letzte Lektion in diesem Kurs (cs_distsys_observability_and_capacity) lehrt, was zu messen, um zu erfahren, dass ein Problem auftritt, bevor die Benutzer es tun. Gesundheitsüberprüfungen, Versionsendpunkte, die vier goldenen Signale auf Proxyebene und wie Entscheidungen über Sprungrahmenkapazität auf beobachtete Daten zurückverweisen.
Kommunales Lektion: geometry_of_failure_modes_and_blast_radius zeigt die zwischenzentrale (welcher Graphknoten ist die Engstelle) und die Min-Schnitt (die Obergrenze für den Sprengsprengweite).
Gut gemacht. Weiter so.