Polly Circuit Breaker excepciones manejadas y no manejadas
Quiero usar Polly para implementar un patrón de disyuntor.
En los documentos, hay una descripción del estado Half Open , y allí dice:
- Si se recibe una excepción manejada, esa excepción se vuelve a lanzar, y el circuito vuelve a abrirse inmediatamente y permanece abierto nuevamente durante el período de tiempo configurado.
- Si se recibe una excepción no controlada, el circuito permanece semiabierto.
No estoy seguro de entender la diferencia aquí entre excepción manejada y no manejada. Estamos describiendo un caso en el que la política ejecuta una acción y genera una excepción.
Cuando dicen que se maneja la excepción, ¿dónde quieren decir que se maneja? porque, como dijimos, la acción lo arrojó, ¿no significa que no está controlado?
Me hace no entender completamente cuándo el estado medio abierto permanece medio abierto y cuándo pasa a estar abierto.
Respuestas
Cuando define una política de disyuntor, puede definir qué tipo de excepciones deben ser consideradas por la implementación de CB . En otras palabras, puede enumerar aquellas excepciones que deberían tratarse como ejecución fallida y deberían contarse en el recuento de fallos sucesivos.
Puede definir la lista de excepciones con la combinación de Handle<T>y Or<T>llamadas a métodos.
Examinemos este concepto a través de un ejemplo simple:
var retry = Policy
.Handle<ArgumentException>()
.Or<NotSupportedException>()
.WaitAndRetry(5, _ => TimeSpan.FromSeconds(1),
onRetry: (exception, delay, context) => Console.WriteLine($"{"Retry",-10}{delay,-10:ss\\.fff}: {exception.GetType().Name}")); var circuitBreaker = Policy .Handle<ArgumentException>() .CircuitBreaker(2, TimeSpan.FromSeconds(1), onBreak: (ex, @break) => Console.WriteLine($"{"Break",-10}{@break,-10:ss\\.fff}: {ex.GetType().Name}"),
onReset: () => Console.WriteLine($"{"Reset",-10}"), onHalfOpen: () => Console.WriteLine($"{"HalfOpen",-10}"));
- La política de disyuntores considera todos
ArgumentExceptionlos correos electrónicos (incluidosArgumentNullExceptionyArgumentOutOfRangeException) como excepción manejada.- Esto significa que si el delegado llamado lanza una de estas tres excepciones, aumentará el recuento de fallas sucesivas y, si se alcanza el umbral, se romperá.
- La política de reintento se activa en caso de
ArgumentExceptiony también en caso deNotSupportedException.- Si se lanza cualquiera de estos, se suspenderá por un segundo y luego intentará volver a ejecutar el mismo delegado.
Entonces, desde la perspectiva del disyuntor, si NotSupportedExceptionse lanza un, no se considerará >> de ahí el nombre no manejado.
Así es como se implementa nuestro método de muestra que arrojará un ArgumentExceptiono un NotSupportedException:
private static int count = 0;
private const int threshold = 3;
static void SampleCall()
{
count++;
if (count >= threshold) throw new NotSupportedException();
throw new ArgumentException("Nothing");
}
El uso de las políticas:
var strategy = Policy.Wrap(retry, circuitBreaker);
try
{
strategy.Execute(SampleCall);
Console.WriteLine("Succeeded");
}
catch (NotSupportedException)
{
Console.WriteLine("Failed");
}
Salida cuando thresholdse establece en 3
Retry 01.000 : ArgumentException
Break 01.000 : ArgumentException
Retry 01.000 : ArgumentException
HalfOpen
Retry 01.000 : NotSupportedException
Retry 01.000 : NotSupportedException
Retry 01.000 : NotSupportedException
Failed
Una vez que el CB se ha transferido al HalfOpenestado, los SampleCalllanzamientos solo son NotSupportedExceptions. Esto no lo maneja el CB, por eso permanece en el HalfOpenestado.
Salida cuando thresholdse establece en 2
Retry 01.000 : ArgumentException
Retry 01.000 : NotSupportedException
Retry 01.000 : NotSupportedException
Retry 01.000 : NotSupportedException
Retry 01.000 : NotSupportedException
Failed
El CB no se rompió porque no hubo dos sucesivos ArgumentException. Pero el reintento se activó porque también maneja NotSupportedException.
Salida cuando thresholdse establece en 4
Retry 01.000 : ArgumentException
Break 01.000 : ArgumentException
Retry 01.000 : ArgumentException
HalfOpen
Break 01.000 : ArgumentException
Retry 01.000 : ArgumentException
HalfOpen
Retry 01.000 : NotSupportedException
Retry 01.000 : NotSupportedException
Failed
Debido a SampleCallque lanzó ArgumentExceptioncuando el CB estaba en el HalfOpenestado, es por eso que CB consideró eso como una excepción manejada y se transfirió de HalfOpena Open.