Condividi tramite


Schema Circuit Breaker

Il Pattern Circuit Breaker aiuta a gestire gli errori che potrebbero richiedere tempi variabili per il recupero quando un'applicazione si connette a un servizio remoto o a una risorsa. Un interruttore blocca temporaneamente l'accesso a un servizio difettoso dopo aver rilevato errori. Questa azione impedisce tentativi ripetuti non riusciti in modo che il sistema possa ripristinarsi in modo efficace. Questo modello può migliorare la stabilità e la resilienza di un'applicazione.

Contesto e problema

In un ambiente distribuito, le chiamate a risorse e servizi remoti possono non riuscire a causa di errori temporanei. Gli errori temporanei includono risorse sovracommesse o temporaneamente non disponibili, connessioni di rete lente o timeout. Questi errori vengono in genere corretti dopo un breve periodo di tempo. Per gestire questi errori, è necessario progettare un'applicazione cloud per usare una strategia, ad esempio il modello di ripetizione dei tentativi .

Gli eventi imprevisti possono creare errori che richiedono più tempo per la correzione. Questi errori possono variare in gravità da una perdita parziale di connettività a un errore completo del servizio. In queste situazioni, un'applicazione non deve ripetere continuamente un'operazione che non è probabile che abbia esito positivo. L'applicazione deve invece riconoscere rapidamente l'operazione non riuscita e gestire di conseguenza l'errore.

Se un servizio è occupato, un errore in una parte del sistema potrebbe causare errori a catena. Ad esempio, è possibile configurare un'operazione che richiama un servizio per implementare un timeout. Se il servizio non risponde entro questo periodo, l'operazione risponde con un messaggio di errore.

Tuttavia, questa strategia può bloccare le richieste simultanee alla stessa operazione fino alla scadenza del periodo di timeout. Queste richieste bloccate potrebbero contenere risorse di sistema critiche, ad esempio memoria, thread e connessioni di database. Questo problema può esaurire le risorse, il che può causare il malfunzionamento di altre parti del sistema non correlate che devono utilizzare le stesse risorse.

In queste situazioni, un'operazione deve avere esito negativo immediatamente e tentare di richiamare il servizio solo se è probabile che abbia esito positivo. Per risolvere il problema, impostare un timeout più breve. Assicurarsi tuttavia che il timeout sia sufficientemente lungo perché l'operazione abbia esito positivo per la maggior parte del tempo.

Soluzione

Il modello interruttore consente di impedire a un'applicazione di tentare ripetutamente di eseguire un'operazione che potrebbe non riuscire. Questo modello consente all'applicazione di continuare l'esecuzione senza attendere che l'errore venga corretto o sprecare cicli di CPU per determinare che l'errore è persistente. Il modello interruttore consente anche a un'applicazione di rilevare quando viene risolto l'errore. Se l'errore viene risolto, l'applicazione può provare a richiamare nuovamente l'operazione.

Nota

Il pattern Circuit Breaker serve uno scopo diverso rispetto al pattern di ripetizione. Il modello Di ripetizione dei tentativi consente a un'applicazione di ritentare un'operazione con l'aspettativa che alla fine abbia esito positivo. Il modello interruttore impedisce a un'applicazione di eseguire un'operazione che potrebbe non riuscire. Un'applicazione può combinare questi due modelli, usando il modello di ripetizione dei tentativi per richiamare un'operazione tramite un interruttore. Tuttavia, la logica di ripetizione dei tentativi deve essere sensibile alle eccezioni restituite dall'interruttore di circuito e interrompere i tentativi di ripetizione se l'interruttore indica che un errore non è temporaneo.

Un interruttore funge da proxy per le operazioni che potrebbero non riuscire. Il proxy deve monitorare il numero di errori recenti e usare queste informazioni per decidere se consentire all'operazione di procedere o restituire immediatamente un'eccezione.

È possibile implementare il proxy come macchina a stati che include gli stati seguenti. Questi stati simulano la funzionalità di un interruttore elettrico:

  • Chiuso: La richiesta dall'applicazione viene instradata all'operazione. Il proxy gestisce un conteggio del numero di errori recenti. Se la chiamata all'operazione non riesce, il proxy incrementa questo conteggio. Se il numero di errori recenti supera una soglia specificata entro un determinato periodo di tempo, il proxy viene inserito nello stato Open e avvia un timer di timeout. Quando il timer scade, il proxy viene inserito nello stato half-open.

    Nota

    Durante il timeout, il sistema tenta di risolvere il problema che ha causato l'errore prima che consenta all'applicazione di tentare nuovamente l'operazione.

  • Open: La richiesta dall'applicazione ha esito negativo immediatamente e viene restituita un'eccezione all'applicazione.

  • Half-Open: Un numero limitato di richieste dall'applicazione può passare e eseguire l'operazione. Se queste richieste hanno esito positivo, l'interruttore presuppone che l'errore che ha causato l'errore sia fisso e che l'interruttore passa allo stato Chiuso. Il contatore degli errori viene reimpostato. Se una richiesta ha esito negativo, l'interruttore presuppone che l'errore sia ancora presente, quindi ripristina lo stato Apri. Riavvia il timer di timeout in modo che il sistema possa riprendersi dall'errore.

    Nota

    Lo stato half-open consente di impedire a un servizio di ripristino di essere improvvisamente inondato di richieste. Durante il ripristino di un servizio, potrebbe essere in grado di supportare un volume limitato di richieste fino al completamento del ripristino. Tuttavia, mentre il ripristino è in corso, un sovraccarico di lavoro può causare il timeout o far fallire di nuovo il servizio.

Il diagramma seguente illustra le operazioni del contatore per ogni stato.

Diagramma che mostra gli stati dell'interruttore.

Il contatore degli errori per lo stato Chiuso è basato sul tempo. Viene reimpostato automaticamente a intervalli periodici. Questa progettazione consente di impedire all'interruttore di immettere lo stato Open se si verificano errori occasionali. La soglia di errore attiva lo stato Open solo quando si verifica un numero specificato di errori durante un intervallo specificato.

Il contatore delle operazioni riuscite per lo stato half-open registra il numero di tentativi riusciti di richiamare l'operazione. L'interruttore torna allo stato Chiuso dopo un numero specificato di chiamate di operazione consecutive. Se un'invocazione ha esito negativo, l'interruttore entra immediatamente nello stato Open e il contatore dei successi si reimposta la volta successiva che entra nello stato Half-Open.

Nota

Il ripristino del sistema si basa su operazioni esterne, ad esempio il ripristino o il riavvio di un componente non riuscito o il ripristino di una connessione di rete.

Il pattern Circuit Breaker offre stabilità mentre il sistema si riprende da un errore e riduce al minimo l'impatto sulle prestazioni. Può aiutare a mantenere il tempo di risposta del sistema. Questo modello rifiuta rapidamente una richiesta per un'operazione che potrebbe non riuscire, anziché attendere il timeout dell'operazione o non ottenere mai una risposta. Se l'interruttore genera un evento ogni volta che cambia stato, queste informazioni possono aiutare a monitorare l'integrità del componente di sistema protetto o avvisare un amministratore quando un interruttore passa allo stato Apri.

È possibile personalizzare e adattare questo modello a diversi tipi di errori. Ad esempio, è possibile applicare un timer di timeout crescente a un interruttore. È possibile posizionare l'interruttore nello stato Apri inizialmente per alcuni secondi. Se l'errore non viene risolto, aumentare il timeout a pochi minuti e regolare di conseguenza. In alcuni casi, anziché restituire un errore e generare un'eccezione, lo stato Open può restituire un valore predefinito significativo per l'applicazione.

Nota

Tradizionalmente, gli interruttori si basavano su soglie preconfigurate, ad esempio il numero di errori e la durata del timeout. Questo approccio ha comportato un comportamento deterministico ma talvolta non ottimale.

Le tecniche adattive che usano intelligenza artificiale e Machine Learning possono regolare dinamicamente le soglie in base a modelli di traffico in tempo reale, anomalie e tassi di errore cronologici. Questo approccio migliora la resilienza e l'efficienza.

Problemi e considerazioni

Quando si implementa questo modello, tenere presenti i fattori seguenti:

  • gestione delle eccezioni: Un'applicazione che richiama un'operazione tramite un interruttore deve essere in grado di gestire le eccezioni se l'operazione non è disponibile. La gestione delle eccezioni si basa sull'applicazione. Ad esempio, un'applicazione potrebbe compromettere temporaneamente la funzionalità, richiamare un'operazione alternativa per tentare di eseguire la stessa attività o ottenere gli stessi dati oppure segnalare l'eccezione all'utente e chiedere di riprovare più tardi.

  • Tipi di eccezioni: I motivi di un errore di richiesta possono variare in gravità. Ad esempio, una richiesta potrebbe non riuscire perché un servizio remoto si arresta in modo anomalo e richiede alcuni minuti per il ripristino o perché un servizio in overload causa un timeout. Un interruttore potrebbe essere in grado di esaminare i tipi di eccezioni che si verificano e regolarne la strategia in base alla natura di queste eccezioni. Ad esempio, potrebbe essere necessario un numero maggiore di eccezioni di timeout per attivare l'interruttore allo stato Aperto rispetto al numero di errori causati dal servizio non disponibile.

  • monitoraggio : un interruttore dovrebbe fornire una chiara visibilità sia sulle richieste non riuscite che su quelle riuscite, in modo che i team operativi possano valutare l'integrità del sistema. Utilizzare il tracciamento distribuito per una visibilità end-to-end tra i servizi.

  • Ripristinabilità: è necessario configurare l'interruttore in modo che corrisponda al modello di recupero probabile dell'operazione che protegge. Ad esempio, se l'interruttore rimane nello stato Open per un lungo periodo, può generare eccezioni anche se il motivo dell'errore viene risolto. Analogamente, un interruttore può variare e ridurre i tempi di risposta delle applicazioni se passa dallo stato Open allo stato Half-Open troppo rapidamente.

  • Test delle operazioni non riuscite: Nello stato open , anziché usare un timer per determinare quando passare allo stato half-open, un interruttore può effettuare periodicamente il ping del servizio remoto o della risorsa per determinare se è disponibile. Questo ping può tentare di richiamare un'operazione precedentemente non riuscita o di usare un'operazione speciale di controllo dell'integrità fornita dal servizio remoto. Per ulteriori informazioni, consulta il modello di monitoraggio degli endpoint della salute .

  • Override manuale: Se il tempo di ripristino per un'operazione non riuscita è estremamente variabile, è necessario fornire un'opzione di reimpostazione manuale che consente a un amministratore di chiudere un interruttore e reimpostare il contatore degli errori. Analogamente, un amministratore può forzare un interruttore nello stato Aperto e riavviare il timer di timeout se l'operazione protetta non è disponibile temporaneamente.

  • Concorrenza: Un numero elevato di istanze simultanee di un'applicazione può accedere allo stesso interruttore automatico. L'implementazione non deve bloccare le richieste simultanee o aggiungere un sovraccarico eccessivo a ogni chiamata a un'operazione.

  • Differenziazione delle risorse: Prestare attenzione quando si usa un singolo interruttore per un tipo di risorsa se potrebbero essere presenti più provider indipendenti sottostanti. Ad esempio, in un archivio dati che contiene più partizioni, una partizione potrebbe essere completamente accessibile mentre un'altra riscontra un problema temporaneo. Se le risposte di errore in questi scenari vengono unite, un'applicazione potrebbe provare ad accedere ad alcuni frammenti anche quando il fallimento è probabile. E l'accesso ad altre partizioni potrebbe essere bloccato anche se è probabile che abbia esito positivo.

  • Interruzione accelerata del circuito: A volte una risposta di errore può fornire abbastanza informazioni per far sì che il circuito si interrompa immediatamente e rimanga interrotto per un tempo minimo. Ad esempio, la risposta di errore da una risorsa condivisa sovraccaricata può indicare che l'applicazione dovrebbe riprovare in pochi minuti, anziché riprovare immediatamente.

  • distribuzioni di più aree: È possibile progettare un interruttore per distribuzioni a singola area o a più aree. Per progettare distribuzioni con più aree, usare i servizi di bilanciamento del carico globale o le strategie di interruzione del circuito personalizzate che consentono di garantire il failover controllato, l'ottimizzazione della latenza e la conformità alle normative.

  • Interruttori di circuito per service mesh: È possibile implementare interruttori di circuito a livello di applicazione o come funzionalità trasversale e astratta. Ad esempio, le mesh di servizio spesso supportano l'interruzione del circuito come sidecar o come funzionalità autonoma senza modificare il codice dell'applicazione.

    Nota

    Un servizio può restituire HTTP 429 (troppe richieste) se limita il client o HTTP 503 (servizio non disponibile) se il servizio non è disponibile. La risposta può includere altre informazioni, ad esempio la durata prevista del ritardo.

  • Riesecuzione delle richieste non riuscite: Nello stato Aperto, invece di fallire rapidamente, un disgiuntore può anche registrare i dettagli di ogni richiesta in un registro e organizzare la riesecuzione di queste richieste quando la risorsa o il servizio remoto diventa disponibile.

  • timeout inappropriati nei servizi esterni: un interruttore A potrebbe non proteggere completamente le applicazioni da errori nei servizi esterni con lunghi periodi di timeout. Se il timeout è troppo lungo, un thread che esegue un interruttore potrebbe essere bloccato per un periodo prolungato prima che l'interruttore indichi che l'operazione non è riuscita. Durante questo periodo, molte altre istanze dell'applicazione potrebbero provare a invocare il servizio tramite il circuit breaker e impegnare numerosi thread prima che tutti falliscano.

  • adattabilità alla diversificazione del calcolo: i interruttori devono tenere conto di ambienti di calcolo diversi, dalla serverless ai carichi di lavoro containerizzati, in cui fattori come l'avvio a freddo e la scalabilità influiscono sulla gestione dei guasti. Gli approcci adattivi possono regolare in modo dinamico le strategie in base al tipo di calcolo, che consente di garantire la resilienza tra architetture eterogenee.

Quando usare questo modello

Usare questo modello quando:

  • Si vuole evitare errori a catena arrestando un numero eccessivo di chiamate al servizio remoto o le richieste di accesso a una risorsa condivisa se queste operazioni potrebbero non riuscire.

  • Si vuole instradare il traffico in modo intelligente in base ai segnali di errore in tempo reale per migliorare la resilienza delle aree.

  • Si vuole proteggersi da dipendenze lente in modo che sia possibile mantenere gli obiettivi a livello di servizio ed evitare una riduzione delle prestazioni dai servizi a latenza elevata.

  • Si vogliono gestire problemi di connettività intermittenti e ridurre gli errori delle richieste negli ambienti distribuiti.

Questo modello potrebbe non essere adatto quando:

  • È necessario gestire l'accesso alle risorse private locali in un'applicazione, ad esempio strutture di dati in memoria. In questo ambiente, un interruttore aggiunge un sovraccarico al sistema.

  • È necessario usarlo come sostituto per la gestione delle eccezioni nella logica di business delle applicazioni.

  • Gli algoritmi di ripetizione noti sono sufficienti e le dipendenze sono progettate per gestire i meccanismi di ripetizione dei tentativi. In questo scenario, un interruttore nell'applicazione potrebbe aggiungere complessità non necessarie al sistema.

  • Attendere il ripristino di un interruttore automatico potrebbe comportare ritardi inaccettabili.

  • Si dispone di un'architettura basata su messaggi o basata su eventi, perché spesso instradano messaggi non riusciti a una coda di messaggi non recapitabili per l'elaborazione manuale o posticipata. L'isolamento degli errori predefinito e i meccanismi di ripetizione dei tentativi sono spesso sufficienti.

  • Il ripristino degli errori viene gestito a livello di infrastruttura o piattaforma, ad esempio con i controlli di integrità nei servizi di bilanciamento del carico globali o nelle mesh dei servizi.

Progettazione del carico di lavoro

Valutare come usare il modello Circuit Breaker nella progettazione di un progetto di carico di lavoro per soddisfare gli obiettivi e i principi trattati nei pilastri Framework di Azure Well-Architected. La tabella seguente fornisce indicazioni su come questo modello supporta gli obiettivi di ogni pilastro.

Pilastro Come questo modello supporta gli obiettivi di pilastro
decisioni di progettazione dell'affidabilità consentono al carico di lavoro di diventare resiliente a un malfunzionamento e assicurano che ripristini a uno stato completamente funzionante dopo che si verifica un guasto. Questo modello aiuta a prevenire il sovraccarico di una dipendenza che presenta errori. Usare questo modello per attivare una riduzione normale del carico di lavoro. Accoppiare gli interruttori con recupero automatico per fornire autoprotezione e auto-riparazione.

- Analisi della modalità errore RE:03
- errori temporanei
- RE:07 Autoconservazione
l'efficienza delle prestazioni consente al carico di lavoro soddisfare in modo efficiente le richieste tramite ottimizzazioni di ridimensionamento, dati e codice. Questo modello evita l'approccio di ritentare in caso di errore, che può causare un utilizzo eccessivo delle risorse durante il recupero delle dipendenze e può sovraccaricare le prestazioni di una dipendenza che sta cercando di recuperare.

- PE:07 Codice e infrastruttura
- PE:11 Risposte ai problemi in diretta

Se questo modello introduce compromessi all'interno di un pilastro, considerarli contro gli obiettivi degli altri pilastri.

Esempio

Questo esempio implementa il modello Circuit Breaker per impedire il sovraccarico della quota usando il livello gratuito a vita Azure Cosmos DB. Questo livello è principalmente per i dati non critici e opera in un piano di capacità che alloca una quota specifica di unità di risorse al secondo. Durante gli eventi stagionali, la domanda potrebbe superare la capacità fornita, il che può comportare risposte 429.

Quando si verificano picchi di domanda, avvisi di Monitoraggio di Azure con soglie dinamiche rilevare e informare in modo proattivo i team operativi e di gestione che il database richiede una maggiore capacità. Contemporaneamente, un interruttore automatico ottimizzato utilizzando modelli di errore storici interviene per prevenire guasti a catena. In questo stato, l'applicazione degrada normalmente restituendo risposte predefinite o memorizzate nella cache. L'applicazione informa gli utenti dell'indisponibilità temporanea di determinati dati mantenendo al tempo stesso la stabilità complessiva del sistema.

Questa strategia migliora la resilienza che si allinea alla motivazione aziendale. Controlla i picchi di capacità in modo che i team del carico di lavoro possano gestire gli aumenti dei costi deliberatamente e mantenere la qualità del servizio senza aumentare in modo imprevisto le spese operative. Dopo che la domanda diminuisce o è confermato l'aumento della capacità, l'interruttore viene reimpostato e l'applicazione ripristina la piena funzionalità in linea con gli obiettivi tecnici e di bilancio.

Diagramma che illustra Azure Cosmos DB e un'implementazione di interruttore automatico in Azure App Service.

Il diagramma include tre sezioni principali. La prima sezione contiene due icone del Web browser. La prima icona visualizza un'interfaccia utente completamente funzionale e la seconda icona mostra un'esperienza utente danneggiata con un avviso sullo schermo per indicare il problema agli utenti. La seconda sezione è racchiusa all'interno di un rettangolo a linea tratteggiata, che è diviso in due gruppi. Il gruppo principale include le risorse del carico di lavoro, il servizio app e Azure Cosmos DB. Le frecce provenienti da entrambe le icone del Web browser puntano all'istanza del servizio app, che rappresenta le richieste in ingresso dal client. Inoltre, le frecce dall'istanza del servizio app puntano ad Azure Cosmos DB, che indicano le interazioni tra i servizi dell'applicazione e il database. Un'altra freccia si ricurva dall'istanza del Servizio App, tornando verso di esso, simbolizzando il meccanismo di timeout del circuito di interruzione. Questo ciclo indica che quando viene rilevata una risposta 429 Troppe richieste, il sistema torna a gestire le risposte memorizzate nella cache, degradando l'esperienza utente fino a quando la situazione non viene risolta. Il gruppo inferiore di questa sezione è incentrato sull'osservabilità e sugli avvisi. Monitoraggio di Azure raccoglie i dati dalle risorse di Azure nel gruppo superiore. Azure Monitor si connette anche a un'icona della regola di allerta. La terza sezione mostra il flusso di lavoro di scalabilità attivato quando viene generato l'avviso. Una freccia connette l'icona dell'avviso agli approvatori, indicando che la notifica viene inviata loro per la revisione. Un'altra freccia conduce dai responsabili dell'approvazione a una console di sviluppo, indicando il processo di approvazione per il ridimensionamento del database. Infine, una freccia successiva si estende dalla console di sviluppo ad Azure Cosmos DB, che illustra l'azione di ridimensionamento del database in risposta alla condizione di overload.

Scarica un file Visio di questa architettura.

Flusso A: Stato chiuso

  • Il sistema funziona normalmente e tutte le richieste raggiungono il database senza restituire alcuna risposta HTTP 429.

  • L'interruttore rimane chiuso e non sono necessarie risposte predefinite o memorizzate nella cache.

Flusso B: Stato aperto

  1. Quando l'interruttore riceve la prima risposta 429, scatta verso uno stato aperto .

  2. Le richieste successive vengono interrotte immediatamente, il che restituisce risposte di default o memorizzate nella cache e informa gli utenti di una temporanea degradazione delle prestazioni. L'applicazione è protetta da un ulteriore overload.

  3. Azure Monitor riceve i log e i dati di telemetria e li valuta rispetto alle soglie dinamiche. Un avviso viene attivato se vengono soddisfatte le condizioni della regola di avviso.

  4. Un gruppo d'azione notifica in modo proattivo al team operativo della condizione di sovraccarico.

  5. Dopo l'approvazione del team di gestione del carico di lavoro, il team operativo può aumentare il throughput fornito per alleviare il sovraccarico o ritardare il ridimensionamento se il carico diminuisce naturalmente.

Flow C: stato Half-Open

  1. Dopo un timeout predefinito, l'interruttore entra in uno stato semiaperto che consente un numero limitato di richieste di prova.

  2. Se queste richieste di prova hanno esito positivo senza restituire risposte 429, il breaker viene reimpostato su uno stato chiuso e le normali operazioni riportano al flusso A. Se gli errori persistono, il breaker torna allo stato aperto o al flusso B.

Componenti

  • servizio app di Azure ospita l'applicazione Web che funge da punto di ingresso primario per le richieste client. Il codice dell'applicazione implementa la logica che applica i criteri di interruttore e fornisce risposte predefinite o memorizzate nella cache quando il circuito è aperto. Questa architettura consente di evitare l'overload nei sistemi downstream e di mantenere l'esperienza utente durante il picco della domanda o degli errori.

  • azure Cosmos DB è uno degli archivi dati dell'applicazione. Fornisce dati non critici tramite il livello gratuito, ideale per carichi di lavoro di produzione di piccole dimensioni. Il meccanismo di interruttore consente di limitare il traffico al database durante periodi di domanda elevata.

  • Azure Monitor funziona come soluzione centrale di monitoraggio. Aggrega tutti i log attività per garantire una completa osservabilità end-to-end. Azure Monitor riceve i log e i dati di telemetria dal Servizio App e le metriche chiave di Azure Cosmos DB (come il numero di risposte 429) per l'aggregazione e l'analisi.

  • Gli avvisi di Azure Monitor valutano le regole di avviso rispetto a alle soglie dinamiche per identificare potenziali interruzioni in base ai dati storici. Gli avvisi predefiniti notificano al team operativo quando le soglie vengono superate.

    In alcuni casi, il team del carico di lavoro potrebbe approvare un aumento del throughput con provisioning, ma il team operativo ritiene che il sistema possa ristabilirsi autonomamente perché il carico non è troppo elevato. In questi casi, il timeout dell'interruttore scade naturalmente. Durante questo periodo di tempo, se le risposte 429 cessano, il calcolo della soglia rileva le interruzioni prolungate ed esclude tali risposte dall'algoritmo di apprendimento. Di conseguenza, la volta successiva che si verifica un overload, la soglia attende una frequenza di errore più elevata in Azure Cosmos DB, che ritarda la notifica. Questa regolazione consente all'interruttore di gestire il problema senza un avviso immediato, migliorando i costi e l'efficienza operativa.

  • Il modello Reliable Web App applica il modello Circuit Breaker alle applicazioni Web che convergono nel cloud.

  • Il modello di ripetizione dei tentativi descrive come un'applicazione può gestire gli errori temporanei previsti quando tenta di connettersi a un servizio o a una risorsa di rete ritentando in modo trasparente un'operazione che in precedenza non è riuscita.

  • Il modello di monitoraggio degli endpoint di integrità descrive come un interruttore può testare l'integrità di un servizio inviando una richiesta a un endpoint esposto dal servizio. Il servizio deve restituire informazioni che ne indicano lo stato.