如果发生异常,Polly框架CircuitBreakerAsync不会重试

时间:2016-04-04 09:17:46

标签: c# async-await circuit-breaker polly

我正在使用Polly框架进行瞬态故障处理。对于同步操作,Polly断路器策略工作正常,但是当我创建其异步版本时,它不会重试执行。请建议:

异步方法

private async static Task HelloWorld()
    {
        if (DateTime.Now < programStartTime.AddSeconds(10))
        {
            Console.WriteLine("Task Failed.");
            throw new TimeoutException();
        }
        await Task.Delay(TimeSpan.FromSeconds(1));
        Console.WriteLine("Task Completed.");
    }

Polly断路器异步策略:

private static void AsyncDemo3(Func<Task> action)
    {
        programStartTime = DateTime.Now;

        Policy policy = Policy
            .Handle<TimeoutException>()
            .CircuitBreakerAsync(3, TimeSpan.FromSeconds(2));
        try
        {
            var a = policy.ExecuteAndCaptureAsync(action, true).GetAwaiter().GetResult();
        }
        catch (AggregateException ex)
        {
            Console.WriteLine("Exception: " + ex.Message);
        }
        catch (Exception ex)
        {
            Console.WriteLine("Exception: " + ex.Message);
        }
    }

执行Polly断路器政策:

AsyncDemo3(HelloWorld的);

请帮助找到并解决问题。

2 个答案:

答案 0 :(得分:12)

我相信你误解了断路器政策的作用。

它的作用是,如果调用它给定的次数并且每次都失败,那么它将停止调用给定的方法一段时间。但它本身并没有重试。

为了做我认为你想做的事情,你需要将重试策略与断路器策略结合起来。一种方法是:

Policy retryPolicy = Policy.Handle<TimeoutException>().RetryAsync(3);

Policy circuitBreakerPolicy = Policy
    .Handle<TimeoutException>()
    .CircuitBreakerAsync(3, TimeSpan.FromSeconds(2));

try
{
    retryPolicy.ExecuteAsync(() => circuitBreakerPolicy.ExecuteAsync(action, true))
        .GetAwaiter().GetResult();
}
…

此代码的输出为:

Task Failed.
Task Failed.
Task Failed.
Exception: The circuit is now open and is not allowing calls.

答案 1 :(得分:1)

建议如下创建两个策略并使用PolicyWrap对其进行组合。

政策创建

 var circuitBreakerPolicy = Policy
        .Handle<TimeoutException>()
        .CircuitBreakerAsync(3, TimeSpan.FromSeconds(2));
 var retryPolicy = Policy.Handle<TimeoutException>().RetryAsync(3);

 // Combined policy: outermost first, innermost last
 var policy = Policy.WrapAsync(retryPolicy, circuitBreakerPolicy);

政策用法

 await this.policy.ExecuteAsync(async () => await SomeFooMethodAsync(cancellationToken));