Compartir a través de


Implementación de reintentos de llamada HTTP con retroceso exponencial con IHttpClientFactory y las directivas de Polly

Sugerencia

Este contenido es un extracto del libro electrónico, ".NET Microservices Architecture for Containerized .NET Applications" (Arquitectura de microservicios de .NET para aplicaciones de .NET contenedorizadas), disponible en Documentación de .NET o como un PDF descargable y gratuito que se puede leer sin conexión.

Miniatura de la portada del libro electrónico 'Arquitectura de microservicios de .NET para aplicaciones .NET contenedorizadas'.

El enfoque recomendado para los reintentos con retroceso exponencial es aprovechar las bibliotecas de .NET más avanzadas, como la biblioteca Polly de código abierto.

Polly es una biblioteca de .NET que proporciona funcionalidades de control de errores transitorios y resistencia. Puede implementar esas funcionalidades aplicando directivas de Polly, como Retry, Circuit Breaker, Bulkhead Isolation, Timeout y Fallback. Polly tiene como destino .NET Framework 4.x y .NET Standard 1.0, 1.1 y 2.0 (que admite .NET Core y versiones posteriores).

En los pasos siguientes se muestra cómo usar reintentos HTTP con Polly integrados en IHttpClientFactory, que se explica en la sección anterior.

Instalación de paquetes .NET

En primer lugar, deberá instalar el Microsoft.Extensions.Http.Polly paquete.

Referencia a los paquetes de .NET 8

IHttpClientFactory está disponible desde .NET Core 2.1, pero se recomienda usar los paquetes de .NET 8 más recientes de NuGet en el proyecto. Normalmente, también debe hacer referencia al paquete de extensión Microsoft.Extensions.Http.Polly.

Configura un cliente con la política de reintento de Polly al iniciar la aplicación

El método AddPolicyHandler() es lo que agrega directivas a los HttpClient objetos que usará. En este caso, se agrega una directiva de Polly para reintentos HTTP con retroceso exponencial.

Para tener un enfoque más modular, la directiva de reintento http se puede definir en un método independiente dentro del archivo Program.cs , como se muestra en el código siguiente:

static IAsyncPolicy<HttpResponseMessage> GetRetryPolicy()
{
    return HttpPolicyExtensions
        .HandleTransientHttpError()
        .OrResult(msg => msg.StatusCode == System.Net.HttpStatusCode.NotFound)
        .WaitAndRetryAsync(6, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2,
                                                                    retryAttempt)));
}

Tal como se muestra en las secciones anteriores, debe definir una configuración HttpClient de cliente con nombre o con tipo en la configuración estándar de la aplicación Program.cs. Ahora agregamos código incremental que especifica la directiva para los reintentos HTTP con retroceso exponencial, tal como se indica a continuación:

// Program.cs
builder.Services.AddHttpClient<IBasketService, BasketService>()
        .SetHandlerLifetime(TimeSpan.FromMinutes(5))  //Set lifetime to five minutes
        .AddPolicyHandler(GetRetryPolicy());

Con Polly, puede definir una directiva de reintento con el número de reintentos, la configuración de retroceso exponencial y las acciones que se deben realizar cuando haya una excepción HTTP, como registrar el error. En este caso, la política está configurada para intentarlo seis veces con un reintento exponencial, iniciando en dos segundos.

Agregar una estrategia de vibración a la directiva de reintentos

Una directiva de reintentos normal puede afectar a su sistema en casos de escalabilidad y simultaneidad altas y de gran contención. Para gestionar los picos de reintentos similares procedentes de diferentes clientes en interrupciones parciales, una buena solución es agregar una estrategia de vibración a la directiva o algoritmo de reintento. Esta estrategia puede mejorar el rendimiento general del sistema de un extremo a otro. Tal y como se recomienda en Polly: reintento con vibración, se puede implementar una buena estrategia de vibración mediante intervalos de reintentos distribuidos y uniformes, aplicados con un intervalo de reintento inicial medio bien controlado en un retroceso exponencial. Este enfoque ayuda a distribuir los picos cuando surge el problema. El principio se muestra en el ejemplo siguiente:


var delay = Backoff.DecorrelatedJitterBackoffV2(medianFirstRetryDelay: TimeSpan.FromSeconds(1), retryCount: 5);

var retryPolicy = Policy
    .Handle<FooException>()
    .WaitAndRetryAsync(delay);

Recursos adicionales