WaitRetryForever 不适用于 Polly.Net 弹性中的自定义异常
WaitRetryForever is not working for a customexception in Polly.Net Resiliency
我有以下 Retry
和 Circuit 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);
如果我使用我的自定义异常,那么我在记录以下内容后重试失败:
- Breaker logging: breaking the circuit for 10000ms!
如果我使用标准 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 次尝试并立即失败。
我有以下 Retry
和 Circuit 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);
如果我使用我的自定义异常,那么我在记录以下内容后重试失败:
- Breaker logging: breaking the circuit for 10000ms!
如果我使用标准 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 次尝试并立即失败。