Implementazione dei tentativi di chiamate HTTP con backoff esponenziale con i criteri di Polly e IHttpClientFactory
Suggerimento
Questo contenuto è un estratto dell'eBook "Microservizi .NET: Architettura per le applicazioni .NET incluse in contenitori", disponibile in .NET Docs o come PDF scaricabile gratuitamente e da poter leggere offline.
L'approccio consigliato per i tentativi con backoff esponenziale prevede l'uso di librerie .NET più avanzate, ad esempio la libreria open source Polly.
Polly è una libreria .NET che fornisce funzionalità di resilienza e di gestione degli errori temporanei. È possibile implementare queste funzionalità applicando i criteri di Polly, ad esempio Retry, Circuit Breaker, Bulkhead Isolation, Timeout e Fallback. Polly è destinato a .NET Framework 4.x e .NET Standard 1.0, 1.1 e 2.0 (che supporta .NET Core e versioni successive).
I passaggi seguenti mostrano come usare i tentativi HTTP con Polly integrato in IHttpClientFactory
, come spiegato nella sezione precedente.
Installare pacchetti .NET
Prima di tutto, è necessario installare il pacchetto Microsoft.Extensions.Http.Polly
.
- Installare con Visual Studio
- Installare con l'interfaccia della riga di comando di dotnet
- Installare con l'interfaccia della riga di comando di nuget.exe
- Installare con la console di Gestione pacchetti (PowerShell)
Fare riferimento ai pacchetti .NET 8
IHttpClientFactory
è disponibile a partire da .NET Core 2.1, tuttavia è consigliabile usare i pacchetti di .NET 8 più recenti da NuGet nel progetto. In genere è anche necessario fare riferimento al pacchetto di estensione Microsoft.Extensions.Http.Polly
.
Configurare un client con i criteri di ripetizione di Polly nell'avvio dell'app
Il metodo AddPolicyHandler() aggiunge i criteri agli oggetti HttpClient
che verranno usati. In questo caso si aggiungono i criteri di Polly per i tentativi HTTP con backoff esponenziale.
Per avere un approccio più modulare, i criteri di ripetizione HTTP possono essere definiti in un metodo separato nel file Program.cs, come illustrato nel codice seguente:
static IAsyncPolicy<HttpResponseMessage> GetRetryPolicy()
{
return HttpPolicyExtensions
.HandleTransientHttpError()
.OrResult(msg => msg.StatusCode == System.Net.HttpStatusCode.NotFound)
.WaitAndRetryAsync(6, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2,
retryAttempt)));
}
Come illustrato nelle sezioni precedenti, è necessario definire una configurazione HttpClient client denominata o tipizzata nella configurazione standard dell'app Program.cs. A questo punto si aggiunge codice incrementale che specifica i criteri per i tentativi HTTP con backoff esponenziale, come indicato di seguito:
// Program.cs
builder.Services.AddHttpClient<IBasketService, BasketService>()
.SetHandlerLifetime(TimeSpan.FromMinutes(5)) //Set lifetime to five minutes
.AddPolicyHandler(GetRetryPolicy());
Con Polly è possibile definire i criteri di ripetizione con il numero di tentativi, la configurazione del backoff esponenziale e le azioni da eseguire quando si verifica un'eccezione HTTP, ad esempio la registrazione dell'errore. In questo caso, i criteri vengono configurati per provare sei volte con un tentativo esponenziale, a partire da due secondi.
Aggiungere una strategia di instabilità ai criteri di ripetizione
I normali criteri di ripetizione possono influire sul sistema quando scalabilità e concorrenza sono elevate e sono presenti molti conflitti. Per risolvere i picchi di tentativi simili provenienti da molti client durante interruzioni parziali, una soluzione alternativa efficace consiste nell'aggiungere una strategia di instabilità all'algoritmo o ai criteri di ripetizione. Questa strategia può migliorare le prestazioni complessive del sistema end-to-end. Come consigliato in Polly: nuovi tentativi con instabilità, una buona strategia di instabilità può essere implementata tramite intervalli di ripetizione uniformi e uniformemente distribuiti applicati con un ritardo iniziale dei tentativi medio ben controllato su un backoff esponenziale. Questo approccio consente di distribuire i picchi quando si verifica il problema. Questo principio è illustrato nell'esempio seguente:
var delay = Backoff.DecorrelatedJitterBackoffV2(medianFirstRetryDelay: TimeSpan.FromSeconds(1), retryCount: 5);
var retryPolicy = Policy
.Handle<FooException>()
.WaitAndRetryAsync(delay);
Risorse aggiuntive
Modello di ripetizione dei tentativihttps://video2.skills-academy.com/azure/architecture/patterns/retry
Polly e IHttpClientFactoryhttps://github.com/App-vNext/Polly/wiki/Polly-and-HttpClientFactory
Polly (libreria .NET con funzionalità di resilienza e gestione degli errori temporanei)https://github.com/App-vNext/Polly
Polly: nuovi tentativi con instabilitàhttps://github.com/App-vNext/Polly/wiki/Retry-with-jitter
Marc Brooker. Jitter: Making Things Better With Randomness (Instabilità: eseguire operazioni meglio con la casualità) https://brooker.co.za/blog/2015/03/21/backoff.html