Wyjątki obsługiwane i nieobsługiwane przez Polly Circuit Breaker

Nov 24 2020

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

1 PeterCsala Nov 25 2020 at 09:20

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 ArgumentExceptions (w tym ArgumentNullExceptioni ArgumentOutOfRangeException) 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 ArgumentExceptioni również w przypadku NotSupportedException.
    • 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 NotSupportedExceptionzostanie wyrzucony, to nie będzie brane pod uwagę >> stąd nazwa nieobsłużona.

Oto jak zaimplementowano naszą przykładową metodę, która wyrzuci ArgumentExceptionznak 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 thresholdjest 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 HalfOpenstanu, SampleCallrzuca tylko NotSupportedExceptions. Nie jest to obsługiwane przez CB, dlatego pozostaje w HalfOpenstanie.

Wyjście, gdy thresholdjest 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 thresholdjest 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ż SampleCallwyrzucił, ArgumentExceptiongdy CB była w HalfOpenstanie, dlatego CB uznała to za obsłużony wyjątek i przeniosła się z HalfOpendo Open.