Share via


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.

.NET Microservices Architecture for Containerized .NET Applications eBook cover thumbnail.

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

Polly es una biblioteca de .NET que proporciona capacidades de resistencia y control de errores transitorios. Puede implementar esas funcionalidades mediante la aplicación de directivas de Polly como las de reintento, interruptor, aislamiento compartimentado, tiempo de espera y reserva. 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 de .NET

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

Referencia a los paquetes de .NET 8

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

Configuración de un cliente con la directiva de reintentos de Polly, en el inicio de la aplicación

El método AddPolicyHandler() es el que agrega las directivas a los objetos HttpClient que se van a 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 reintentos HTTP se puede definir en un método independiente en el archivo Program.cs, tal 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, se puede definir una directiva de reintentos con el número de reintentos, la configuración de retroceso exponencial y las acciones necesarias cuando se produce una excepción de HTTP, como registrar el error. En este caso, la directiva está configurada para intentar seis veces con un reintento exponencial, a partir de 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 que rige esto 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