Wyjątki obsługiwane i nieobsługiwane przez Polly Circuit Breaker
Chcę użyć Polly do zaimplementowania wzorca wyłącznika.
W dokumentach znajduje się opis stanu Half Open , a tam jest napisane:
- Jeśli otrzymany zostanie obsłużony wyjątek, wyjątek ten jest ponownie zgłaszany, a obwód natychmiast przechodzi z powrotem do otwarcia i pozostaje otwarty ponownie przez skonfigurowany przedział czasu.
- Jeśli zostanie odebrany nieobsługiwany wyjątek, obwód pozostaje w połowie otwarty.
Nie jestem pewien, czy rozumiem różnicę między obsłużonym a nieobsługiwanym wyjątkiem. Opisujemy przypadek, w którym akcja jest uruchamiana przez politykę i zgłasza wyjątek.
Kiedy mówią, że wyjątek jest obsługiwany, gdzie mają na myśli, że jest obsługiwany? ponieważ jak powiedzieliśmy, akcja rzuciła to, czy nie oznacza to, że jest nieobsługiwana?
To sprawia, że nie rozumiem całkowicie, kiedy stan półotwarty pozostaje w połowie otwarty, a kiedy przechodzi w stan otwarty.
Odpowiedzi
Podczas definiowania zasad dotyczących wyłączników można zdefiniować, jakiego rodzaju wyjątki powinny być uwzględniane przez implementację CB . Innymi słowy, możesz wymienić te wyjątki, które powinny być traktowane jako nieudane wykonanie i powinny być wliczane do liczby kolejnych niepowodzeń.
Możesz zdefiniować listę wyjątków za pomocą kombinacji Handle<T>
i Or<T>
wywołań metod.
Przyjrzyjmy się tej koncepcji na prostym przykładzie:
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}"));
- Zasady dotyczące wyłączników automatycznych traktują wszystkie
ArgumentException
s (w tymArgumentNullException
iArgumentOutOfRangeException
) jako obsługiwane wyjątki.- Oznacza to, że jeśli wywoływany delegat zgłosi jeden z tych trzech wyjątków, to zwiększy liczbę kolejnych niepowodzeń, a jeśli próg zostanie osiągnięty, nastąpi zerwanie.
- Zasady ponawiania są wyzwalane w przypadku
ArgumentException
i również w przypadkuNotSupportedException
.- Jeśli któryś z nich zostanie wyrzucony, będzie spał przez sekundę, a następnie spróbuje ponownie wykonać tego samego delegata.
Zatem z perspektywy wyłącznika, jeśli NotSupportedException
zostanie wyrzucony, to nie będzie brane pod uwagę >> stąd nazwa nieobsłużona.
Oto jak zaimplementowano naszą przykładową metodę, która wyrzuci ArgumentException
znak lub 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");
}
Stosowanie polityk:
var strategy = Policy.Wrap(retry, circuitBreaker);
try
{
strategy.Execute(SampleCall);
Console.WriteLine("Succeeded");
}
catch (NotSupportedException)
{
Console.WriteLine("Failed");
}
Wyjście, gdy threshold
jest ustawione na 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
Po przeniesieniu CB do HalfOpen
stanu, SampleCall
rzuca tylko NotSupportedException
s. Nie jest to obsługiwane przez CB, dlatego pozostaje w HalfOpen
stanie.
Wyjście, gdy threshold
jest ustawione na 2
Retry 01.000 : ArgumentException
Retry 01.000 : NotSupportedException
Retry 01.000 : NotSupportedException
Retry 01.000 : NotSupportedException
Retry 01.000 : NotSupportedException
Failed
CB nie pękło, ponieważ nie było dwóch kolejnych ArgumentException
. Ale ponowna próba wyzwoliła, ponieważ obsługuje również NotSupportedException
.
Wyjście, gdy threshold
jest ustawione na 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
Ponieważ SampleCall
wyrzucił, ArgumentException
gdy CB była w HalfOpen
stanie, dlatego CB uznała to za obsłużony wyjątek i przeniosła się z HalfOpen
do Open
.