Implementare la resilienza delle applicazioni
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:
- Aggiungere il
Microsoft.Extensions.Http.Resilience
pacchetto al progetto. - Aggiungere un gestore di resilienza alle chiamate al servizio HttpClient.
- 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.
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 WebApplication
e 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. |
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.