Nota:
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
La resistencia es la capacidad de una aplicación para recuperarse de errores transitorios y seguir funcionando. En el contexto de la programación de .NET, la resistencia se logra mediante el diseño de aplicaciones que pueden controlar los errores correctamente y recuperarse rápidamente. Para ayudar a crear aplicaciones resistentes en .NET, los dos paquetes siguientes están disponibles en NuGet:
| Paquete de NuGet | Descripción |
|---|---|
| 📦 Microsoft.Extensions.Resilience | Este paquete NuGet proporciona mecanismos para proteger las aplicaciones frente a errores transitorios. |
| 📦 Microsoft.Extensions.Http.Resilience | Este paquete NuGet proporciona mecanismos de resistencia específicos para la HttpClient clase . |
Estos dos paquetes NuGet se basan en Polly, que es un proyecto de código abierto popular. Polly es una biblioteca de resiliencia y gestión de errores transitorios de .NET que permite a los desarrolladores expresar estrategias como reintento, disyuntor, tiempo de espera, aislamiento compartimentado, limitación de velocidad, reserva y cobertura de manera fluida y segura para los subprocesos.
Importante
El paquete NuGet Microsoft.Extensions.Http.Polly está en desuso. Use cualquiera de los paquetes mencionados anteriormente en su lugar.
Comienza
Para empezar a trabajar con la resistencia en .NET, instale el paquete NuGet Microsoft.Extensions.Resilience .
dotnet add package Microsoft.Extensions.Resilience
Para obtener más información, consulte Dotnet Package add or Manage package dependencies in .NET applications (Agregar o administrar dependencias de paquetes en aplicaciones .NET).
Creación de una canalización de resistencia
Para usar la resiliencia, primero debe desarrollar una serie de estrategias basadas en resiliencia. Cada estrategia configurada se ejecuta en orden de configuración. En otras palabras, el orden es importante. El punto de entrada es un método de extensión en el IServiceCollection tipo , denominado AddResiliencePipeline. Este método toma un identificador de la canalización y un delegado que configura la canalización. Al delegado se le pasa una instancia de ResiliencePipelineBuilder, que se usa para agregar estrategias de resiliencia a la canalización.
Considere el siguiente ejemplo basado en key cadenas:
using Microsoft.Extensions.DependencyInjection;
using Polly;
using Polly.CircuitBreaker;
using Polly.Registry;
using Polly.Retry;
using Polly.Timeout;
var services = new ServiceCollection();
const string key = "Retry-Timeout";
services.AddResiliencePipeline(key, static builder =>
{
// See: https://www.pollydocs.org/strategies/retry.html
builder.AddRetry(new RetryStrategyOptions
{
ShouldHandle = new PredicateBuilder().Handle<TimeoutRejectedException>()
});
// See: https://www.pollydocs.org/strategies/timeout.html
builder.AddTimeout(TimeSpan.FromSeconds(1.5));
});
El código anterior:
- Crea una nueva instancia de
ServiceCollection. - Define un
keypara identificar la tubería. - Agrega una canalización de resiliencia a la instancia de
ServiceCollection. - Configura la canalización con estrategias de reintento y tiempo de espera.
Cada canalización está configurada para un determinado key, y cada key se usa para identificar su correspondiente ResiliencePipeline al obtener la canalización del proveedor.
key es un parámetro de tipo genérico del AddResiliencePipeline método .
Extensiones del generador de canalizaciones de resiliencia
Para agregar una estrategia a la canalización, llame a cualquiera de los métodos de extensión Add* disponibles en la instancia ResiliencePipelineBuilder.
-
AddRetry: inténtelo de nuevo si se produce un error, lo que resulta útil cuando el problema es temporal y podría desaparecer. -
AddCircuitBreaker: deje de intentar si algo está roto o ocupado, lo que le beneficia evitando el tiempo desperdiciado y empeorando las cosas. -
AddTimeout: Abandonar si algo tarda demasiado, lo que puede mejorar el rendimiento al liberar recursos. -
AddRateLimiter: limite cuántas solicitudes acepte, lo que le permite controlar la carga entrante. -
AddConcurrencyLimiter: limite cuántas solicitudes realice, lo que le permite controlar la carga saliente. -
AddFallback: realice otra acción al experimentar errores, lo que mejora la experiencia del usuario. -
AddHedging: emita varias solicitudes en caso de alta latencia o error, lo que puede mejorar la capacidad de respuesta.
Para obtener más información, consulte Estrategias de resistencia. Para obtener ejemplos, consulte Compilación de aplicaciones HTTP resistentes: patrones de desarrollo de claves.
Enriquecimiento de métricas
El enriquecimiento es el aumento automático de la telemetría con un estado conocido, en forma de pares nombre-valor. Por ejemplo, una aplicación podría emitir un registro que incluya la operación y el código de resultado como columnas para representar el resultado de alguna operación. En esta situación y en función del contexto periférico, el enriquecimiento agrega el nombre del clúster, el nombre del proceso, la región, el identificador de inquilino y mucho más al registro a medida que se envía al back-end de telemetría. Cuando se agrega el enriquecimiento, el código de la aplicación no necesita hacer nada adicional para beneficiarse de las métricas enriquecidas.
Funcionamiento del enriquecimiento
Imagine 1000 instancias de servicio distribuidas globalmente que generan registros y métricas. Cuando se produce un problema en el panel de servicio, es fundamental identificar rápidamente la región problemática o el centro de datos. El enriquecimiento garantiza que los registros de métricas contengan la información necesaria para identificar los errores en los sistemas distribuidos. Sin enriquecimiento, la carga cae en el código de la aplicación para administrar internamente este estado, integrarlo en el proceso de registro y transmitirlo manualmente. El enriquecimiento simplifica este proceso, controlándolo sin problemas sin afectar a la lógica de la aplicación.
En el caso de resistencia, al agregar enriquecimiento se agregan las siguientes dimensiones a la telemetría saliente:
-
error.type: versión de cardinalidad baja de la información de una excepción. -
request.name: nombre de la solicitud. -
request.dependency.name: nombre de la propiedad de dependencia.
En segundo plano, el enriquecimiento de la resiliencia se basa en MeteringEnricher de la telemetría de Polly. Para obtener más información, consulte Polly: medición del enriquecimiento.
Agregar enriquecimiento de resiliencia
Además de registrar una canalización de resiliencia, también puede registrar el enriquecimiento de resiliencia. Para agregar enriquecimiento, llame al método de extensiones AddResilienceEnricher(IServiceCollection) en la instancia IServiceCollection.
services.AddResilienceEnricher();
Al llamar al método de extensión AddResilienceEnricher, añades dimensiones sobre las que vienen por defecto integradas en Polly. Se agregan las siguientes dimensiones de enriquecimiento:
- Enriquecimiento de excepciones basado en IExceptionSummarizer, que proporciona un mecanismo para resumir las excepciones que se usan en la telemetría. Para obtener más información, vea Resumen de excepciones.
- Solicitar el enriquecimiento de metadatos mediante RequestMetadata, que contiene los metadatos de la solicitud para la telemetría. Para más información, consulte Polly: Métricas de telemetría.
Usar la canalización de resiliencia
Para usar una canalización de resiliencia configurada, debe obtener la canalización de un ResiliencePipelineProvider<TKey>. Cuando agregó la canalización antes, key era de tipo string, por lo que debe obtener la canalización de ResiliencePipelineProvider<string>.
using ServiceProvider provider = services.BuildServiceProvider();
ResiliencePipelineProvider<string> pipelineProvider =
provider.GetRequiredService<ResiliencePipelineProvider<string>>();
ResiliencePipeline pipeline = pipelineProvider.GetPipeline(key);
El código anterior:
- Construye un
ServiceProvidera partir de la instanciaServiceCollection. - Obtiene el
ResiliencePipelineProvider<string>del proveedor de servicios. - Recupera el
ResiliencePipelinedesde elResiliencePipelineProvider<string>.
Ejecutar una canalización de resiliencia
Para utilizar la canalización de resiliencia, llame a cualquiera de los métodos Execute* disponibles de la instancia ResiliencePipeline. Por ejemplo, considere una llamada de ejemplo al ExecuteAsync método :
await pipeline.ExecuteAsync(static cancellationToken =>
{
// Code that could potentially fail.
return ValueTask.CompletedTask;
});
El código anterior ejecuta el delegado dentro del método ExecuteAsync. Cuando hay errores, se ejecutan las estrategias configuradas. Por ejemplo, si RetryStrategy está configurado para reintentar tres veces, el delegado se ejecuta cuatro veces (un intento inicial más tres reintentos) antes de que se propague el error.