Implementare la resilienza delle applicazioni

Completato

Le funzionalità di resilienza di .NET sono basate sul progetto Polly e rese disponibili tramite Microsoft.Extensions. È possibile aggiungere una strategia di resilienza standard che usa impostazioni predefinite sensibili aggiungendo una singola riga di codice all'app.

Aggiungere resilienza all'app

Per aggiungere resilienza a un'app compilata usando un'architettura di microservizi, usare richieste HTTP tra singoli servizi, seguire questa procedura:

  1. Aggiungere il Microsoft.Extensions.Http.Resilience pacchetto al progetto.
  2. Aggiungere un gestore di resilienza alle chiamate al servizio HttpClient.
  3. Configurare la strategia di resilienza.

Aggiungere il pacchetto NuGet al progetto

Eseguire il comando seguente per aggiungere il pacchetto NuGet con resilienza:

dotnet add package Microsoft.Extensions.Http.Resilience

L'esecuzione di questo comando dal terminale nella cartella del progetto app aggiungerà il riferimento al pacchetto al file di progetto.

Nella classe di avvio dell'applicazione aggiungere l'istruzione using seguente:

using Microsoft.Extensions.Http.Resilience;

Aggiungere una strategia di resilienza

È ora possibile aggiungere una strategia di resilienza standard al servizio HttpClient. .NET offre questa configurazione predefinita che combina una serie di strategie.

A diagram showing the strategies included in the Standard Resilience Handler. From overall timeout, retry, bulkhead, circuit breaker, and attempt timeout.

Il gestore delle richieste esegue ognuna delle strategie precedenti in ordine da sinistra a destra:

  • Strategia di timeout totale delle richieste: imposta un periodo totale di tempo che la richiesta può richiedere. Si può pensare a questo come impostare il limite di tempo superiore per tutte le altre strategie.
  • Strategia di ripetizione dei tentativi: questa strategia controlla le opzioni in base al numero di tentativi, backoff e jitter. Queste opzioni non possono superare il timeout totale impostato nella strategia precedente.
  • Strategia dell'interruttore: questa strategia apre il circuito se il rapporto di errore supera la soglia.
  • Strategia di timeout dei tentativi: questa strategia imposta un timeout per ogni singola richiesta. Se la richiesta richiede più tempo di questo tempo, viene generata un'eccezione.

È possibile aggiungere questa strategia standard, con tutti i valori predefiniti aggiungendo questo metodo di estensione:

.AddStandardResilienceHandler();

Ad esempio, se è stato dichiarato un WebApplicatione si vuole aggiungere una strategia di resilienza al servizio HttpClient, usare questo codice:

builder.Services.AddHttpClient<ServiceBeingCalled>(httpClient =>
{
    httpClient.BaseAddress = new Uri("https://service.endpoint/");
}).AddStandardResilienceHandler();

La prima riga del codice precedente aggiunge un gestore di resilienza standard a HTTPClient. Verranno usate tutte le impostazioni predefinite per le strategie di ripetizione e interruttore.

Configurare la strategia di resilienza

È possibile modificare i valori predefiniti di una delle strategie specificando nuove opzioni, ad esempio:

.AddStandardResilienceHandler( options => 
{  
    options.RetryOptions.RetryCount = 10;
    options.RetryOptions.BaseDelay = TimeSpan.FromSeconds(1);
});

Questo codice modifica per impostazione predefinita la strategia di ripetizione dei tentativi in modo da avere un numero massimo di ritiri pari a 10, per usare un back off lineare e usare un ritardo di base di 1 secondo.

Le opzioni scelte devono essere compatibili tra loro. Ad esempio, se il tempo totale rimane come predefinito di 30 secondi, le opzioni di ripetizione dei tentativi precedenti causeranno un'eccezione. Si tratta di un errore perché l'impostazione di backoff esponenziale causerebbe il completamento totale dei 10 tentativi di 2046 secondi. Si tratta di un'eccezione di runtime, non di un errore in fase di compilazione.

Nella tabella seguente sono elencate le opzioni disponibili per ognuna delle strategie.

Opzioni di timeout delle richieste totali Descrizione
TotalTimeout Quantità totale di tempo che la richiesta può richiedere. Il valore predefinito è 30 secondi.
OnTimeout Funzione di callback richiamata al timeout della richiesta. Il valore predefinito è Null.

Opzioni di ripetizione dei tentativi Descrizione
RetryCount Numero massimo di tentativi. Il valore predefinito è 3.
BackoffType Tipo di backoff da utilizzare. È possibile scegliere tra lineare ed esponenziale. Il valore predefinito è esponenziale.
UseJitter Indica se aggiungere jitter al backoff. Il jitter aggiunge casualità al ritardo per ridurre i picchi di carico. Il valore predefinito è true.
BaseDelay L'intervallo tra i tentativi. Il valore predefinito è 2 secondi.

Opzioni dell'interruttore Descrizione
BreakDuration Durata dell'interruzione del circuito. Il valore predefinito è 5 secondi.
FailureRatio Rapporto tra richieste non riuscite e richieste riuscite che apriranno il circuito. Il valore predefinito è 0,1.
SamplingDuration Durata del tempo in cui viene calcolato il rapporto di errore. Il valore predefinito è 30 secondi.
OnClosed Funzione di callback richiamata quando il circuito viene chiuso. Il valore predefinito è Null.
OnHalfOpened Funzione di callback richiamata quando il circuito è semi-aperto. Il valore predefinito è Null.
OnOpened Funzione di callback richiamata all'apertura del circuito. Il valore predefinito è Null.

Opzioni di timeout tentativo Descrizione
Timeout Quantità di tempo che la richiesta può richiedere. Il valore predefinito è 2 secondi.
OnTimeout Funzione di callback richiamata al timeout della richiesta. Il valore predefinito è Null.

A sequence diagram showing the flow of events in an application using a resiliency strategy.

Il diagramma di sequenza precedente mostra come ognuna delle strategie interagiscono in una strategia di resilienza standard. Per iniziare con il fattore di limitazione della durata di una richiesta è controllato dalla strategia di timeout totale. La strategia di ripetizione dei tentativi deve quindi essere impostata per avere un numero massimo di tentativi che verranno completati entro il timeout totale. La strategia dell'interruttore aprirà il circuito se il rapporto di errore supera la soglia impostata. La strategia di timeout dei tentativi imposta un timeout per ogni singola richiesta. Se la richiesta richiede più tempo di questo tempo, viene generata un'eccezione.