I Tre Concetti di Fallimento da Conoscere
Benvenuto
I sistemi distribuiti falliscono in modi stereotipati. Appena impari questi modi, ogni postmortem diventa un esercizio di riconoscimento invece di un mistero.
Tre concetti coprono la maggior parte di ciò che conta nell'analisi delle fallite in produzione:
Punto Unico di Fallimento (SPOF): un componente la cui fallita porta giù un sistema più grande. Spesso nascosto: il server DNS su cui tutti dipendono; il certificato che tutto rinnova contro; il database master unico.
Fallita a Catena: la fallita di un componente attiva un altro, che attiva un altro. Un database lento causa timeout nell'API tier, che causa ritmi, che carica ulteriormente il database, che causa più timeout. L'esplosione si diffonde.
Raggio di Distruzione: quanto della struttura va giù quando una pezza fallisce. Le scelte architettoniche limitano o non limitano il raggio. Un SPOF ha un raggio di distruzione illimitato. Un servizio bulkhead ha un raggio limitato.
Alla fine di questa lezione, tu sarai in grado di:
- Identificare SPOF in un'architettura per ispezione
- Riconoscere i modi stereotipati di fallita a catena: stormo di uccelli, tempesta di ritmi, coda di coda
- Leggere un vero timeline e separare il trigger dalla fallita latente che il trigger ha portato in superficie
- Scrivere azioni senza colpe che mirano ai sistemi invece delle persone, coprendo prevenzione/detect/recovery
- Ragionare su bulkhead e circuit breakers come strumenti per limitare il raggio di distruzione
Individua il Punto Unico di Fallimento
Ispezione dell'Architettura Strato per Strato
Considera una piccola architettura web:
- DNS: api.example.com -> IP del server nameserver singolo 203.0.113.10 ospitato da un solo fornitore DNS
- CDN: un unico fornitore CDN davanti a api.example.com
- Ingresso: due macchine reverse proxy dietro un load balancer
- Back-end: sei replica API in due zone di disponibilità (tre per zona)
- Database: un primario + un replica di lettura, nella stessa zona di disponibilità
- Cache: cluster Redis, tre nodi sparsi nelle stesse due zone di disponibilità
Domanda: quali componenti sono SPOF? Suggerimento: i SPOF non sono sempre la 'macchina singola' ovvia. Un cluster di tre macchine tutte in una sola zona di disponibilità è un SPOF per il fallimento della zona.
Tre modelli classici di cascata
Le falliture si propagano attraverso le dipendenze
Modello 1: Stormo di fulmini. Un risorsa condivisa (cache, lock, database) fallisce o riavvia. Ogni cliente che dipendeva da essa riprova contemporaneamente. L'onda d'urto sopraffa ciò che viene rimesso in funzione; le riprovazioni si accumulano più velocemente della loro assorbimento; la ripresa non si completa mai.
Modello 2: Tempesta di riprovazioni. Un servizio downstream rallenta. Gli chiamanti upstream, invece di fallire, riprovano. Le riprovazioni moltiplicano la carica originale. Il servizio downstream si rallenta ancora, provocando ancora più riprovazioni. Infine, la carica supera anche una versione sana del servizio.
Modello 3: Coda di morte. Una coda di elaborazione senza backpressure riceve più velocemente di quanto venga elaborata. La coda cresce senza limiti. L'esaurimento della memoria fa cadere il consumatore; riavvio; trova una coda ancora più grande; cade di nuovo.
Filo conduttore comune: una piccola perturbazione iniziale scatena un ciclo positivo. La risposta del sistema amplifica la fallita invece di ammorzarla.
Mecanismi di ammortizzazione
Ritardo esponenziale con scostamento. I clienti che riprovano aspettano più a lungo ogni volta, con un offset casuale. Evita le onde sincrone di riprovazione.
Interruttori di sicurezza. Un chiamante traccia la percentuale di fallimenti downstream. Oltre un certo limite, il chiamante smette di chiamare per un periodo di raffreddamento e fallisce immediatamente le proprie richieste. Evita il lavoro sprecato e permette al downstream di riprendersi.
Scotta di carico. Isola le risorse per dipendenza. Piscina di connessioni A per il database, piscina di connessioni B per il cache. Un database lento non può affamare tutte le connessioni; le chiamate al cache continuano.
Svergadino. Quando sovraccarico, rifiuta le richieste all'ingresso invece di accettarle e fallire lentamente. Un 429 in 1 ms è meglio di un 500 in 30 secondi.
Backpressure. Lenti i produttori quando i consumatori non possono tenere il passo. Le code diventano limitate; i mittenti bloccano; la fonte originale di lavoro sente la frizione.
Diagnosi di una Cascata
Un team dell'API si scioglie durante un failover di database routinario. Cronologia:
- 14:00:00 — operatore promuove il database di standby. Disponibilità prevista: ~10 secondi.
- 14:00:08 — il primario è inattivo. Gli errori di connessione al database delle richieste API iniziano a fallire.
- 14:00:08 — l'API riprova (configurazione predefinita: 5 riprovazioni, nessuna backoff, 100ms di intervallo).
- 14:00:11 — il standby viene promosso e accetta nuove connessioni.
- 14:00:11 — l'API apre migliaia di nuove connessioni al database contemporaneamente (ogni replica × ogni richiesta concorrente × ogni riprova).
- 14:00:13 — la nuova primaria esaurisce la piscina delle connessioni e rifiuta nuove connessioni.
- 14:00:13-14:05:00 — le replicate dell'API esauriscono le piscine delle connessioni, lanciano eccezioni, si fermano, ricominciano, ripetono.
- 14:05:00 — l'operatore interrompe manualmente il traffico dell'API tier; il database si stabilizza.
- 14:10:00 — la restituzione graduale del traffico è completa. Interruzione totale: ~10 minuti (contro l'atteso ~10 secondi).
SERVFAIL DNS: Due Difetti Congiunti
Un Postmortem di Verità
Ciò che segue è una versione sanificata di un vero incidente. I nomi dei fornitori sono cambiati, gli IP sono stati anonimizzati; la forma, la cronologia e le lezioni sono reali.
Riassunto
Il sito example.com ha restituito SERVFAIL da tutti i resolver DNS pubblici per circa 3-4 ore. Tutte le altre 46 zone su quel stesso master DNS erano immuni. La causa radice: due difetti congiunti.
1. Vendor A (un fornitore secondario di DNS) ha aggiunto un nuovo IP di sincronizzazione interno che non era incluso nella lista di consentimento allow-axfr-ips del primario.
2. La zona example.com aveva un conflitto CNAME di anni con violazione RFC (demo.example.com aveva sia CNAME che MX/TXT allo stesso label) che ha causato Vendor A a rifiutare la zona su AXFR fresco.
Cronologia (UTC)
- ~15:00 — Vendor A aggiunge nuovo IP di sincronizzazione 198.51.100.42 nella loro infrastruttura
- 15:02 — prima di AXFR-out denied per 198.51.100.42 appare nei log del DNS primario (nessun allertamento su questo segnale)
- ~18:00 — si raggiunge la finestra del SOA expire; Vendor A elimina la zona example.com dalla cache
- ~18:30 — si verifica un SERVFAIL esternamente
- ~19:45 — si identifica la causa radice
- 20:00 — 198.51.100.42 aggiunto a allow-axfr-ips; il primario è stato riavviato
- 20:05 — viene inviato un NOTIFY; viene avviata un'AXFR; la zona RIMANE SERVFAIL (conflitto CNAME)
- 20:07 — check-zone rivela 1 errore: conflitto CNAME su demo.example.com
- 20:09 — viene sostituito il CNAME con un record A; il controllo della zona è pulito (0 errori)
- 20:10 — viene inviato un NOTIFY; l'AXFR si completa; Vendor A inizia a servire la zona
- 20:11 — dig @8.8.8.8 example.com A restituisce l'IP corretto — RISOLTO
Perché solo example.com?
Le 47 zone condividono lo stesso DNS primario. La blocco AXFR ha interessato tutte le zone. Ma solo example.com aveva il conflitto CNAME e solo example.com aveva bisogno di un AXFR fresco nel momento in cui era stata applicata la negazione. Le altre zone avevano già aggiornato prima della negazione o non avevano ancora bisogno di aggiornarsi.
Difetto latente
Il conflitto CNAME a demo.example.com esisteva da anni. Funzionava perché il primario serviva la zona dal suo database (generoso riguardo alle violazioni RFC) e Vendor A serviva da dati di cache vecchi rispetto alla violazione introdotta. Quando Vendor A ha eliminato la cache e ha avuto bisogno di dati freschi, la violazione è emersa.
Scatenante
Vendor A ha aggiunto in silenzio un nuovo indirizzo di sincronizzazione. La lista di concessione del primario non lo includeva. L'AXFR è stato negato. Tre ore dopo (SOA expire), Vendor A ha eliminato la zona. Il difetto latente è emerso quando il sistema ha cercato di riprendersi.
Scrivi Azioni di Responsabilità Incolpativa
Incolpativo senza colpa: mira ai sistemi, non alle persone
Un'azione di responsabilità incolpativa nomina qualcosa che il sistema dovrebbe fare diversamente, non qualcosa che una persona dovrebbe fare diversamente. 'Addestrare l'operatore' è colpevole. 'Aggiungere un controllo automatizzato che individui questo prima del lancio' è senza colpa.
Le buone azioni di responsabilità incolpativa si raggruppano in tre dimensioni:
- Prevenzione: rendere la cattiva cosa più difficile o impossibile
- Detezione: notarlo prima se accade
- Ripresa: limitare il danno quando accade
Ogni elemento dovrebbe nominare (1) il cambiamento specifico del sistema, (2) un team proprietario e (3) la dimensione a cui serve.
Compartimenti che affondano senza l'astronave
Prestito da ingegneria navale
Le navi hanno paratie stagni: muri verticali che dividono la carena in compartimenti. Un compartimento può affondare senza far affondare la nave; un altro può fallire senza influire sull'altro.
I sistemi distribuiti prendono lo stesso termine e la stessa idea.
Pattern delle paratie: isolare le risorse per dipendenza. Un servizio che chiama tre API downstream utilizza tre piscine di connessioni separate, tre budget di thread separate. Un downstream lento o che fallisce non può consumare le risorse assegnate agli altri due.
Senza paratie: una dipendenza lenta esaurisce la pool di thread condiviso; le chiamate alle altre dipendenze bloccano in attesa di thread; l'intero servizio diventa non rispondente.
Con paratie: una dipendenza lenta esaurisce la propria pool; le chiamate a essa falliscono rapidamente; le chiamate alle altre dipendenze continuano normalmente; il raggio d'esplosione rimane limitato alla dipendenza che fallisce.
Interruttori di protezione
Pattern dell'interruttore di protezione: un involucro a stato che circonda una dipendenza downstream che traccia la percentuale di fallimenti. Tre stati:
- Chiuso (normale): le chiamate passano attraverso. I fallimenti vengono conteggiati.
- Aperto (trippato): oltre a un soglia di fallimento (ad esempio, il 50% di fallimenti negli ultimi 30 secondi), il breaker si apre. Le chiamate falliscono immediatamente senza cercare la dipendenza. Salva il chiamante dal perdere lavoro; salva la dipendenza dal ricevere carico mentre è poco sana.
- Mezzo aperto (test): dopo un periodo di raffreddamento, il breaker permette una piccola percentuale di chiamate attraverso. Se riescono, si chiude di nuovo al normale. Se falliscono, si riapre per un altro periodo di raffreddamento.
La chiave: l'interruttore di protezione prevene lo sforzo sprecato durante periodi di non salute conosciuta, e dà alla dipendenza una possibilità di riprendersi senza carico continuo.
Le paratie limitano il raggio d'esplosione. Gli interruttori di protezione impediscono all'esplosione di durare.
Limita il raggio d'esplosione
La tua API service chiama quattro servizi downstream: User Service, Recommendation Service, Notification Service e un Payment API di terze parti. La squadra ha sentito che 'la Recommendation Service non è stata molto affidabile' e vuole assicurarsi che quando fallisce, il resto del sistema rimanga sano.
Oggi il servizio utilizza una sola pool di thread condivisa di 200 thread e una sola pool di connessioni HTTP condivise. Tutti e quattro i downstream competono per queste risorse. Non ci sono circuit breakers.
Progetta una revisione dei modi di fallire
Sinossi
Hai imparato a individuare le SPOFs per ispezione, a riconoscere i modi di fallire a cascata, a separare il trigger dalla difetta latente leggendo un postmortem, a scrivere azioni punitive attraverso la prevenzione, la detezione e il recupero, a limitare il raggio d'azione con bulkheads + circuit breakers + decrescita gradita.
Applica tutti e cinque.
La tua squadra sta lanciando un nuovo servizio search.example.com che dipende da tre servizi downstream: un indice di ricerca principale (index.example.com), un servizio di analisi (analytics.example.com) e un servizio di raccomandazioni (recs.example.com). La squadra vuole che tu conduca una 'revisione dei modi di fallire' prima del lancio.
Dove va questo corso
Dove va questo corso
Ora puoi individuare una SPOF, riconoscere una cascata, leggere un postmortem in modo produttivo, scrivere azioni punitive e limitare il raggio d'azione progettando la sicurezza.
La lezione finale in questo corso (cs_distsys_observability_and_capacity) insegna cosa misurare per scoprire che un problema sta avvenendo prima che gli utenti lo facciano. Controlli di salute, endpoint di versione, le quattro segnali d'oro a una tier di proxy, & come le decisioni di capacità di picco si legano ai dati osservati.
Lezione correlata: geometry_of_failure_modes_and_blast_radius deriva la centralità di betweenness (qual è il nodo grafo che è il bottigliaazzo?) & min-cut (il limite sul raggio di espansione).
Ben fatto. In avanti.