Polly Circuit Breaker 处理和未处理的异常

Polly Circuit Breaker handled and unhandled exceptions

我想使用 Polly 来实现断路器模式。

在文档中,有一个 description of the Half Open state,上面写着:

  • If a handled exception is received, that exception is rethrown, and the circuit transitions immediately back to open, and remains open again for the configured timespan.
  • If an unhandled exception is received, the circuit remains in half-open.

我不确定我是否理解已处理异常和未处理异常之间的区别。我们正在描述一种情况,其中操作是 运行 策略并抛出异常。

当他们说异常被处理时,他们指的是什么地方被处理了?因为正如我们所说,动作抛出它是否意味着它未处理?

搞不懂什么时候半开还是半开,什么时候过渡到开

当您定义断路器策略时,您可以定义 CB implementation 应考虑哪种类型的异常。换句话说,您可以列出那些应被视为执行失败并应计入连续失败计数的异常。

您可以结合使用 Handle<T>Or<T> 方法调用来定义异常列表。

让我们通过一个简单的例子来仔细研究这个概念:

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}"));
  • 断路器策略将所有 ArgumentException(包括 ArgumentNullExceptionArgumentOutOfRangeException)视为已处理的异常。
    • 这意味着如果被调用的委托抛出这三个异常之一,那么它将增加连续失败计数,如果达到阈值,它将中断。
  • 重试策略在 ArgumentExceptionNotSupportedException 的情况下被触发。
    • 如果抛出其中任何一个,它将休眠一秒钟,然后尝试重新执行同一个委托。

因此,从断路器的角度来看,如果 NotSupportedException 被抛出,则不会被考虑 >> 因此名称未处理。

这就是我们的示例方法的实现方式,它会抛出 ArgumentExceptionNotSupportedException:

private static int count = 0;
private const int threshold = 3;
static void SampleCall()
{
    count++;
    if (count >= threshold) throw new NotSupportedException();
    throw new ArgumentException("Nothing");
}

政策的用途:

var strategy = Policy.Wrap(retry, circuitBreaker);

try
{
    strategy.Execute(SampleCall);
    Console.WriteLine("Succeeded");
}
catch (NotSupportedException)
{
    Console.WriteLine("Failed");
}

threshold设置为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

CB 将自身转移到 HalfOpen 状态后,SampleCall 仅抛出 NotSupportedExceptions。这不是由 CB 处理的,这就是它保持 HalfOpen 状态的原因。

threshold设置为2

时的输出
Retry     01.000    : ArgumentException
Retry     01.000    : NotSupportedException
Retry     01.000    : NotSupportedException
Retry     01.000    : NotSupportedException
Retry     01.000    : NotSupportedException
Failed

CB没有断,因为没有连续两次ArgumentException。但是重试确实触发了,因为它还处理了 NotSupportedException.

threshold设置为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

因为当 CB 处于 HalfOpen 状态时 SampleCall 确实抛出 ArgumentException 这就是为什么 CB 将其视为已处理的异常并将其自身从 HalfOpen 转移到 Open.