【问题标题】:Polly circuitbreaker is not being calledPolly 断路器没有被调用
【发布时间】:2021-10-28 01:40:38
【问题描述】:

我第一次尝试实施断路器,但它不起作用。后备政策有效,但我似乎无法达到断路器。我已经在不同的版本中尝试过这个,包括断路器的重试策略,但这似乎并不重要。我确定这是我错过的基本内容。

这是用于测试目的的代码的简化版本:

var timeoutPolicy = Policy
            .TimeoutAsync(
                _settings.TimeoutWhenCallingApi,
                TimeoutStrategy.Pessimistic
            );

        var circuitBreaker = Policy
            .Handle<TimeoutRejectedException>()
            .CircuitBreakerAsync(
                _settings.ConsecutiveExceptionsAllowedBeforeBreaking,
                _settings.DurationOfBreak
            )
            .WrapAsync(timeoutPolicy);

        policy = Policy
            .Handle<Exception>()
            .FallbackAsync(
                async cancellationToken => { Console.WriteLine("fallback triggered"); })
            .WrapAsync(circuitBreaker);

        await policy.ExecuteAsync(() => Task.Delay(-1));

【问题讨论】:

  • 嗨!当您期望断路器“工作”/“到达”时,您是否能够发布您正在使用的完整代码? (也就是说:你有你希望触发电路中断的代码?或者?)。到目前为止发布的代码只有一个调用await policy.ExecuteAsync(() =&gt; Task.Delay(-1));。只有当_settings.ConsecutiveExceptionsAllowedBeforeBreaking 连续调用失败时,电路才会中断。因此,从目前发布的代码来看,只有_settings.ConsecutiveExceptionsAllowedBeforeBreaking == 1 时电路才会中断。
  • 也可能相关:您在此处定义的circuitBreaker 策略不会吸收TimeoutRejectedException(如果这是您所期望的)。在计算出现次数后,它将重新抛出它。断路器只是一种测量和(如果超过故障阈值)分断装置,但它会重新抛出所有异常。请参阅:github.com/App-vNext/Polly/wiki/…stackoverflow.com/a/37101237。希望这可以帮助。如果不是,您能否定义您期望但未看到的行为? - 你所说的“到达”断路器是什么意思,或者它正在“工作”?
  • 还有:这是一个dotnetfiddle sample,显示断路器工作。 Polly Samples 编号 6、7 及以后的示例可以从 Visual Studio 或类似工具中运行。

标签: circuit-breaker polly


【解决方案1】:

以下代码示例构建的超时、断路器和回退策略与您问题中发布的原始代码基本相同。

using Polly; 
using System;
using System.Threading.Tasks;

public class Program
{
    public static async void Main() {

    var timeoutPolicy = Policy
        .TimeoutAsync(
            TimeSpan.FromMilliseconds(10), // _settings.TimeoutWhenCallingApi,
            Polly.Timeout.TimeoutStrategy.Pessimistic
        );

    var circuitBreaker = Policy
        .Handle<Polly.Timeout.TimeoutRejectedException>()
        .CircuitBreakerAsync(
            1, // _settings.ConsecutiveExceptionsAllowedBeforeBreaking,
            TimeSpan.FromSeconds(30) // _settings.DurationOfBreak
        );
    var circuitBreakerWrappingTimeout = circuitBreaker
        .WrapAsync(timeoutPolicy);

    var policy = Policy
        .Handle<Exception>()
        .FallbackAsync(
            async cancellationToken => { Console.WriteLine("fallback triggered"); })
        .WrapAsync(circuitBreakerWrappingTimeout);

    Console.WriteLine("Circuit state before execution: " + circuitBreaker.CircuitState);
    
    await policy.ExecuteAsync(() => Task.Delay(-1));
    
    Console.WriteLine("Circuit state after execution: " + circuitBreaker.CircuitState);
    }
}

可以使用此 dotnetfiddle 示例运行代码:https://dotnetfiddle.net/m9O3cg

(dotnetfiddle 示例更改为非异步 main 只是因为 dotnetfiddle 并不总是 await async Main() 方法完成,所以输出并不总是与 async Main() 完成)

输出是:

Circuit state before execution: Closed
fallback triggered
Circuit state after execution: Open

这表明断路器政策正在达到/参与您的执行。

  • 执行的委托被超时策略超时,抛出TimeoutRejectedException
  • 熔断器策略捕捉到它并计算它经历的连续TimeoutRejectedExceptions 的数量:1. 这足以断开,因此熔断器转换为打开状态。
  • 断路器重新投掷TimeoutRejectedException(它只是一个测量和分断装置)
  • 后备策略捕获 TimeoutRejectedException 并输出后备。
  • 最终线路输出电路状态表明断路器受到(因此参与)调用的影响。

由于电路开路,在 30 秒内通过policy 执行durationOfBreak 将失败并显示BrokenCircuitException

【讨论】:

  • 非常感谢!不知何故,我错过了我只打过一次电话......但你的进一步解释也对我制定最终的实际政策有很大帮助。完美!
猜你喜欢
  • 1970-01-01
  • 2019-09-08
  • 1970-01-01
  • 2018-10-10
  • 1970-01-01
  • 2021-03-07
  • 2016-07-10
  • 1970-01-01
  • 2019-07-22
相关资源
最近更新 更多