WaitRetryForever 不适用于 Polly.Net 弹性中的自定义异常

WaitRetryForever is not working for a customexception in Polly.Net Resiliency

我有以下 RetryCircuit Breaker 政策:

var waitAndRetryPolicy = Policy
    .Handle<Exception>(e => e is MycustomException)
    .WaitAndRetryForeverAsync(
        attempt => TimeSpan.FromMilliseconds(500),
        (exception, calculatedWaitDuration) =>
        {
            _logger.LogInfo(exception.GetType().FullName);
            _logger.LogInfo(".Log,then retry: " + exception.Message);
        });

var circuitBreakerPolicy = Policy
    .Handle<Exception>()
    .CircuitBreakerAsync(
        4,
        TimeSpan.FromSeconds(10),
        (ex, breakDelay) =>
        {
            _logger.LogError(".Breaker logging: Breaking the circuit for " + breakDelay.TotalMilliseconds + "ms!");
        },
        () => { _logger.LogError(".Breaker logging: Call ok! Closed the circuit again!"); },
        () => { _logger.LogError(".Breaker logging: Half-open: Next call is a trial!"); }
    );

return waitAndRetryPolicy.WrapAsync(circuitBreakerPolicy);

如果我使用我的自定义异常,那么我在记录以下内容后重试失败:

如果我使用标准 Exception 类型,它工作正常。即使断路器打开也会重试:

 var waitAndRetryPolicy = Policy
.Handle<Exception>()
.WaitAndRetryForeverAsync(
    attempt => TimeSpan.FromMilliseconds(500),
    (exception, calculatedWaitDuration) =>
    {
        _logger.LogInfo(exception.GetType().FullName);
        _logger.LogInfo(".Log,then retry: " + exception.Message);
    });

当断路器打开时,所有后续请求都会立即被 BrokenCircuitException 拒绝。这意味着如果重试在断路器打开的那个时间段内触发,那么如果您只查找自定义异常,它将不会处理它。这就是为什么您的弹性策略到此为止并抛出异常的原因。

如果您想对两者都应用重试(当断路器打开时和自定义异常被抛出时),那么您必须使用 Or<> 构建器函数。

var waitAndRetryPolicy = Policy
    .Handle<Exception>(e => e is MycustomException)
    .Or<BrokenCircuitException>
    .WaitAndRetryForeverAsync(
        attempt => TimeSpan.FromMilliseconds(500),
        (exception, calculatedWaitDuration) =>
        {
            _logger.LogInfo(exception.GetType().FullName);
            _logger.LogInfo(".Log,then retry: " + exception.Message);
        });

请记住,时机在这里很重要。您的断路器会等待 10 秒,然后才会自行转换为半开状态。在此期间,重试将尝试执行几次尝试,但它们将立即失败。每次尝试失败后,它都会休眠 500 毫秒。这意味着在 10 秒内(当断路器打开时)重试执行 ~20 次尝试并立即失败。