7

我正在使用 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);

请帮助查找并解决问题。

4

2 回答 2

14

I believe you misunderstood what the circuit breaker policy does.

What it does is that if you call it the given number of times and it fails each time, then it will stop calling the given method for a certain amount of time. But it does not retry by itself.

So to do what I think you want to do, you need to combine retry policy with circuit breaker policy. One way to do that would be:

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();
}
…

The output of this code is:

Task Failed.
Task Failed.
Task Failed.
Exception: The circuit is now open and is not allowing calls.
于 2016-04-04T12:26:07.327 回答
2

建议使用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));
于 2020-02-18T23:09:17.677 回答