In aumento MTBF - Disponibilità e oltre: comprensione e miglioramento della resilienza dei sistemi distribuiti su AWS

Le traduzioni sono generate tramite traduzione automatica. In caso di conflitto tra il contenuto di una traduzione e la versione originale in Inglese, quest'ultima prevarrà.

In aumento MTBF

L'ultimo componente per migliorare la disponibilità è l'aumento diMTBF. Ciò può applicarsi sia al software che ai AWS servizi utilizzati per eseguirlo.

Aumento del sistema distribuito MTBF

Un modo per aumentare MTBF è ridurre i difetti del software. Esistono vari modi per eseguire questa operazione. I clienti possono utilizzare strumenti come Amazon CodeGuru Reviewer per trovare e correggere errori comuni. È inoltre necessario eseguire revisioni complete del codice tra pari, test unitari, test di integrazione, test di regressione e test di carico sul software prima che venga distribuito in produzione. L'aumento della copertura del codice nei test contribuirà a garantire che vengano testati anche i percorsi di esecuzione del codice non comuni.

L'implementazione di modifiche minori può anche aiutare a prevenire risultati imprevisti riducendo la complessità delle modifiche. Ogni attività offre l'opportunità di identificare e correggere i difetti prima che possano essere invocati.

Un altro approccio per prevenire i guasti è costituito dai test regolari. L'implementazione di un programma di ingegneria del caos può aiutare a verificare gli errori del carico di lavoro, a convalidare le procedure di ripristino e a individuare e correggere le modalità di errore prima che si verifichino in produzione. I clienti possono utilizzare AWS Fault Injection Simulator come parte del loro set di strumenti per esperimenti di ingegneria del caos.

La tolleranza ai guasti è un altro modo per prevenire i guasti in un sistema distribuito. Moduli fail-fast, nuovi tentativi con backoff e jitter esponenziali, transazioni e idempotenza sono tutte tecniche che contribuiscono a rendere i carichi di lavoro tolleranti ai guasti.

Le transazioni sono un gruppo di operazioni che aderiscono alle proprietà. ACID Essi sono i seguenti:

  • Atomicità: o tutte le azioni si verificano o nessuna di esse accadrà.

  • Coerenza: ogni transazione lascia il carico di lavoro in uno stato valido.

  • Isolamento: le transazioni eseguite contemporaneamente lasciano il carico di lavoro nello stesso stato come se fossero state eseguite in sequenza.

  • Durabilità: una volta completata la transazione, tutti i suoi effetti vengono preservati anche in caso di errore del carico di lavoro.

I nuovi tentativi con backoff e jitter esponenziali consentono di superare i guasti transitori causati da Heisenbug, sovraccarico o altre condizioni. Quando le transazioni sono idempotenti, possono essere ritentate più volte senza effetti collaterali.

Se consideriamo l'effetto di un Heisenbug su una configurazione hardware tollerante ai guasti, non saremmo affatto preoccupati, poiché la probabilità che l'Heisenbug compaia sia sul sottosistema primario che su quello ridondante è infinitesimale. (Vedi Jim Gray, "Perché i computer si fermano e cosa si può fare al riguardo? «, giugno 1985, Tandem Technical Report 85.7.) Nei sistemi distribuiti, vogliamo ottenere gli stessi risultati con il nostro software.

Quando viene richiamato un Heisenbug, è fondamentale che il software rilevi rapidamente l'operazione errata e fallisca in modo che possa essere riprovato. Ciò si ottiene attraverso una programmazione difensiva e la convalida degli input, dei risultati intermedi e dell'output. Inoltre, i processi sono isolati e non condividono lo stato con altri processi.

Questo approccio modulare garantisce che l'ambito di impatto in caso di guasto sia limitato. I processi falliscono indipendentemente. Quando un processo fallisce, il software deve utilizzare delle «coppie di processi» per riprovare a eseguire il lavoro, il che significa che un nuovo processo può assumere il funzionamento di un processo fallito. Per mantenere l'affidabilità e l'integrità del carico di lavoro, ogni operazione deve essere trattata come una transazione. ACID

Ciò consente il fallimento di un processo senza alterare lo stato del carico di lavoro, interrompendo la transazione e ripristinando le modifiche apportate. Ciò consente al processo di ripristino di ritentare la transazione da uno stato riconosciuto valido e di riavviarla correttamente. Questo è il modo in cui il software può essere tollerante ai guasti nei confronti di Heisenbugs.

Tuttavia, non dovresti mirare a rendere il software tollerante ai guasti nei confronti di Bohrbugs. Questi difetti devono essere individuati e rimossi prima che il carico di lavoro entri in produzione, poiché nessun livello di ridondanza porterà mai a risultati corretti. (Vedi Jim Gray, "Perché i computer si fermano e cosa si può fare al riguardo? «, giugno 1985, Tandem Technical Report 85.7.)

L'ultimo modo per aumentare MTBF è ridurre la portata dell'impatto derivante da un guasto. L'utilizzo dell'isolamento dei guasti mediante la modularizzazione per creare contenitori di guasti è un modo fondamentale per farlo, come illustrato in precedenza in Tolleranza agli errori e isolamento dei guasti. La riduzione del tasso di errore migliora la disponibilità. AWS utilizza tecniche come la suddivisione dei servizi in piani di controllo e piani dati, l'indipendenza dalla zona di disponibilità (AZI), l'isolamento regionale, le architetture basate su celle e lo shuffle-sharding per fornire l'isolamento dai guasti. Questi sono modelli che possono essere utilizzati anche dai clienti. AWS

Ad esempio, esaminiamo uno scenario in cui un carico di lavoro ha collocato i clienti in diversi contenitori di guasto della sua infrastruttura che servivano al massimo il 5% del totale dei clienti. In uno di questi contenitori di errore si verifica un evento che ha aumentato la latenza oltre il timeout del client per il 10% delle richieste. Durante questo evento, per il 95% dei clienti, il servizio era disponibile al 100%. Per il restante 5%, il servizio sembrava disponibile al 90%. Ciò si traduce in una disponibilità di 1 − (5% o f c u s t o m e r s × 10% o f t h e i r r e q u e s t s) = 99,5% anziché il 10% delle richieste non riuscite per il 100% dei clienti (con una disponibilità del 90%).

Regola 11

L'isolamento dei guasti riduce la portata dell'impatto e aumenta il carico MTBF di lavoro riducendo il tasso di guasto complessivo.

Aumento della dipendenza MTBF

Il primo metodo per aumentare la AWS dipendenza MTBF consiste nell'utilizzare l'isolamento dei guasti. Molti AWS servizi offrono un livello di isolamento in una AZ, il che significa che un guasto in una AZ non influisce sul servizio in un'altra AZ.

L'utilizzo di istanze ridondanti in più EC2 istanze AZs aumenta la disponibilità del sottosistema. AZIoffre una funzionalità di risparmio all'interno di una singola regione, che consente di aumentare la disponibilità dei servizi. AZI

Tuttavia, non tutti i AWS servizi funzionano a livello di AZ. Molti altri offrono l'isolamento regionale. In questo caso, se la disponibilità prevista del servizio regionale non supporta la disponibilità complessiva richiesta per il carico di lavoro, potresti prendere in considerazione un approccio multiregionale. Ogni regione offre un'istanza isolata del servizio, equivalente a sparing.

Esistono vari servizi che aiutano a semplificare la creazione di un servizio multiregionale. Per esempio:

Questo documento non approfondisce le strategie di creazione di carichi di lavoro multiregionali, ma è necessario valutare i vantaggi in termini di disponibilità delle architetture multiregionali con i costi aggiuntivi, la complessità e le pratiche operative necessarie per raggiungere gli obiettivi di disponibilità desiderati.

Il metodo successivo per aumentare la dipendenza consiste nel progettare il carico di lavoro in modo che MTBF sia staticamente stabile. Ad esempio, hai un carico di lavoro che serve informazioni sul prodotto. Quando i tuoi clienti richiedono un prodotto, il tuo servizio invia una richiesta a un servizio di metadati esterno per recuperare i dettagli del prodotto. Quindi il carico di lavoro restituisce tutte queste informazioni all'utente.

Tuttavia, se il servizio di metadati non è disponibile, le richieste effettuate dai clienti hanno esito negativo. Puoi invece estrarre o inviare localmente i metadati in modo asincrono al tuo servizio in modo asincrono per utilizzarli per rispondere alle richieste. In questo modo si elimina la chiamata sincrona al servizio di metadati dal percorso critico.

Inoltre, poiché il servizio è ancora disponibile anche quando il servizio di metadati non lo è, puoi rimuoverlo come dipendenza nel calcolo della disponibilità. Questo esempio si basa sul presupposto che i metadati non vengano modificati frequentemente e che la pubblicazione di metadati obsoleti sia preferibile all'esito negativo della richiesta. Un altro esempio simile è serve-stale for DNS che consente di conservare i dati nella cache oltre la TTL scadenza e di utilizzarli per le risposte quando una risposta aggiornata non è prontamente disponibile.

L'ultimo metodo per aumentare la dipendenza consiste nel ridurre la portata dell'impatto MTBF derivante da un errore. Come accennato in precedenza, il fallimento non è un evento binario, ma vi sono diversi gradi di fallimento. Questo è l'effetto della modularizzazione; l'errore è limitato solo alle richieste o agli utenti serviti da quel contenitore.

Ciò si traduce in un minor numero di errori durante un evento, il che in ultima analisi aumenta la disponibilità del carico di lavoro complessivo limitando l'ambito dell'impatto.

Riduzione delle fonti di impatto comuni

Nel 1985, Jim Gray scoprì, durante uno studio presso Tandem Computers, che il fallimento era causato principalmente da due fattori: il software e le operazioni. (Vedi Jim Gray, "Perché i computer si fermano e cosa si può fare al riguardo? «, giugno 1985, Tandem Technical Report 85.7.) Anche dopo 36 anni, questo continua ad essere vero. Nonostante i progressi tecnologici, non esiste una soluzione semplice a questi problemi e le principali fonti di fallimento non sono cambiate. La risoluzione dei guasti nel software è stata discussa all'inizio di questa sezione, quindi l'attenzione sarà rivolta alle operazioni e alla riduzione della frequenza dei guasti.

Stabilità rispetto alle funzionalità

Se facciamo riferimento al grafico dei tassi di errore per software e hardware nella sezioneDisponibilità del sistema distribuito, possiamo notare che i difetti vengono aggiunti in ogni versione del software. Ciò significa che qualsiasi modifica al carico di lavoro comporta un aumento del rischio di fallimento. Queste modifiche sono in genere cose come nuove funzionalità, che ne forniscono un corollario. Una maggiore disponibilità dei carichi di lavoro favorirà la stabilità rispetto alle nuove funzionalità. Pertanto, uno dei modi più semplici per migliorare la disponibilità consiste nell'implementare meno spesso o fornire meno funzionalità. I carichi di lavoro che vengono implementati più frequentemente avranno intrinsecamente una disponibilità inferiore rispetto a quelli che non lo fanno. Tuttavia, i carichi di lavoro che non aggiungono funzionalità non tengono il passo con la domanda dei clienti e possono diventare meno utili nel tempo.

Quindi, come possiamo continuare a innovare e rilasciare funzionalità in modo sicuro? La risposta è la standardizzazione. Qual è il modo corretto di implementazione? Come si ordinano le distribuzioni? Quali sono gli standard per i test? Quanto tempo aspetti tra una fase e l'altra? I vostri test unitari coprono una parte sufficiente del codice software? Si tratta di domande a cui la standardizzazione può rispondere e prevenire problemi causati da fattori come il mancato test di carico, il salto delle fasi di implementazione o l'implementazione troppo rapida su troppi host.

Il modo in cui si implementa la standardizzazione avviene attraverso l'automazione. Riduce la possibilità di errori umani e consente ai computer di fare ciò in cui sono bravi, ovvero fare la stessa cosa più e più volte nello stesso modo ogni volta. Il modo per unire standardizzazione e automazione consiste nel fissare degli obiettivi. Obiettivi come l'assenza di modifiche manuali, l'accesso all'host solo tramite sistemi di autorizzazione contingente, la stesura di test di carico per tutti API e così via. L'eccellenza operativa è una norma culturale che può richiedere cambiamenti sostanziali. Stabilire e monitorare le prestazioni rispetto a un obiettivo aiuta a promuovere un cambiamento culturale che avrà un ampio impatto sulla disponibilità del carico di lavoro. Il pilastro AWS Well-Architected Operational Excellence fornisce best practice complete per l'eccellenza operativa.

Sicurezza degli operatori

L'altro fattore importante che contribuisce agli eventi operativi che determinano il fallimento sono le persone. Gli esseri umani commettono errori. Potrebbero utilizzare le credenziali sbagliate, immettere il comando sbagliato, premere Invio troppo presto o perdere un passaggio fondamentale. L'esecuzione di azioni manuali comporta costantemente errori, con conseguente fallimento.

Una delle cause principali degli errori degli operatori sono le interfacce utente confuse, poco intuitive o incoerenti. Jim Gray ha anche osservato nel suo studio del 1985 che «le interfacce che richiedono informazioni all'operatore o gli chiedono di eseguire alcune funzioni devono essere semplici, coerenti e tolleranti ai guasti dell'operatore». (Vedi Jim Gray, "Perché i computer si fermano e cosa si può fare al riguardo? «, giugno 1985, Tandem Technical Report 85.7.) Questa intuizione continua ad essere vera oggi. Negli ultimi tre decenni in tutto il settore ci sono numerosi esempi in cui un'interfaccia utente confusa o complessa, la mancanza di conferme o istruzioni o anche solo un linguaggio umano ostile hanno indotto un operatore a fare la cosa sbagliata.

Regola 12

Fai in modo che gli operatori facciano facilmente la cosa giusta.

Prevenzione del sovraccarico

L'ultimo fattore comune che contribuisce all'impatto sono i vostri clienti, gli utenti effettivi del vostro carico di lavoro. I carichi di lavoro efficaci tendono a essere utilizzati spesso, ma a volte tale utilizzo supera la capacità di scalabilità del carico di lavoro. Ci sono molte cose che possono succedere, i dischi possono riempirsi, i pool di thread potrebbero esaurirsi, la larghezza di banda della rete potrebbe essere saturata o si possono raggiungere i limiti di connessione al database.

Non esiste un metodo infallibile per eliminarli, ma il monitoraggio proattivo della capacità e dell'utilizzo tramite le metriche di Operational Health fornirà avvisi tempestivi quando potrebbero verificarsi questi guasti. Tecniche come la riduzione del carico, gli interruttori automatici e i nuovi tentativi con backoff e jitter esponenziali possono contribuire a ridurre al minimo l'impatto e aumentare la percentuale di successo, ma queste situazioni rappresentano comunque un fallimento. La scalabilità automatizzata basata su metriche di Operational Health può aiutare a ridurre la frequenza dei guasti dovuti al sovraccarico, ma potrebbe non essere in grado di rispondere abbastanza rapidamente ai cambiamenti di utilizzo.

Se è necessario garantire la disponibilità continua della capacità per i clienti, è necessario scendere a compromessi in termini di disponibilità e costi. Un modo per garantire che la mancanza di capacità non porti all'indisponibilità è fornire a ciascun cliente una quota e garantire che la capacità del carico di lavoro sia scalata in modo da fornire il 100% delle quote assegnate. Quando i clienti superano la loro quota, vengono limitati, il che non è un problema e non influisce sulla disponibilità. Dovrai inoltre monitorare attentamente la tua base clienti e prevedere l'utilizzo futuro per mantenere una capacità sufficiente. Ciò garantisce che il carico di lavoro non sia ricondotto a scenari di errore dovuti a un consumo eccessivo da parte dei clienti.

Ad esempio, esaminiamo un carico di lavoro che fornisce un servizio di storage. Ogni server del carico di lavoro può supportare 100 download al secondo, ai clienti viene fornita una quota di 200 download al secondo e i clienti sono 500. Per poter supportare questo volume di clienti, il servizio deve fornire una capacità di 100.000 download al secondo, il che richiede 1.000 server. Se un cliente supera la propria quota, viene limitato, il che garantisce una capacità sufficiente per tutti gli altri clienti. Questo è un semplice esempio di un modo per evitare il sovraccarico senza scartare le unità di lavoro.