Reziliență Enterprise în .NET: Implementarea Pattern-urilor Retry, Circuit Breaker și Rate Limiting cu Polly și IHttpClientFactory în C# (.NET)

Ghid complet de producție pentru reziliența apelurilor de rețea în .NET 8: utilizarea pachetului Microsoft.Extensions.Http.Resilience, integrarea cu Polly v8, pattern-urile Circuit Breaker, Exponential Backoff și evitarea Socket Exhaustion.

Sintaxă C#
builder.Services.AddHttpClient('api').AddStandardResilienceHandler(); | Polly v8

În arhitecturile de microservicii distribuite, căderile temporare de rețea, supraîncărcarea tranzitorie a serverelor partenere (coduri HTTP 429 sau 503) și instabilitatea conexiunilor externe sunt evenimente normale de viață. O aplicație robustă nu trebuie să cedeze la prima eroare temporară, ci trebuie să implementeze strategii automate de reziliență.

În .NET 8, Microsoft a colaborat oficial cu echipa bibliotecii de referință Polly (v8) pentru a lansa pachetul unificat Microsoft.Extensions.Http.Resilience, care activează cele mai bune practici din industrie printr-o singură linie de cod declarativ!

Activarea Pipeline-ului Standard de Reziliență în .NET 8
// Instalare pachet oficial:
// dotnet add package Microsoft.Extensions.Http.Resilience

var builder = WebApplication.CreateBuilder(args);

// Înregistrăm un client HTTP configurat nativ cu cele 5 strategii standard de producție:
builder.Services.AddHttpClient("GatewayPlati", client =>
{
    client.BaseAddress = new Uri("https://api.plati-securizate.ro");
    client.DefaultRequestHeaders.Add("User-Agent", "DexBlogEnterprise/2.0");
})
// O singură linie injectează pipeline-ul complet de reziliență enterprise:
.AddStandardResilienceHandler(options =>
{
    // Personalizăm politicile în funcție de contractul de SLA:
    options.Retry.MaxRetryAttempts = 3;
    options.Retry.BackoffType = Polly.DelayBackoffType.Exponential;
    options.Retry.UseJitter = true; // Zgomot aleator pentru a preveni Cache Stampede
    options.TotalRequestTimeout.Timeout = TimeSpan.FromSeconds(10);
    options.CircuitBreaker.SamplingDuration = TimeSpan.FromSeconds(30);
    options.CircuitBreaker.FailureRatio = 0.5; // Deschide circuitul dacă 50% din cereri eșuează
});

Cele 5 Niveluri Defensive ale AddStandardResilienceHandler

  1. Total Request Timeout: Garantează că întreaga operațiune (inclusiv toate reîncercările cumulate) nu depășește un prag maxim absolut (ex: 10 secunde).
  2. Retry cu Exponential Backoff și Jitter: Reîncearcă automat apelurile eșuate din motive tranzitorii (latență de rețea, erori 5xx, 429), mărind timpul de așteptare exponențial cu variație aleatorie (jitter) pentru a nu copleși serverul partener.
  3. Circuit Breaker: Dacă serviciul extern este complet căzut și eșuează constant, circuitul se „deschide” și respinge imediat cererile locale timp de 30 de secunde, protejând resursele aplicației și oferind serverului partener timp să își revină.
  4. Attempt Timeout: Limitează durata fiecărei încercări individuale la un prag scurt (ex: 2 secunde).
  5. Rate Limiter (Concurrency Limiter): Restricționează numărul de cereri paralele transmise către API-ul extern pentru a nu depăși cota alocată.

Prevenirea Epuizării Porturilor (Socket Exhaustion)

Nu instanțiați niciodată manual new HttpClient() într-un bloc using! Chiar și după Dispose(), socket-ul TCP de sistem de operare rămâne blocat în starea TIME_WAIT timp de până la 4 minute. Folosirea exclusivă a IHttpClientFactory garantează reutilizarea optimă a socket-urilor active și reîmprospătarea periodică a rezolvărilor DNS.