ASP.NET Core 微服务初探[2]:熔断降级之Polly (2)

重试就是指Polly在调用失败时捕获我们指定的异常,并重新发起调用,如果重试成功,那么对于调用者来说,就像没有发生过异常一样。在网络调用中经常出现瞬时故障,那么重试机制就非常重要。

一个简单的重试策略定义如下:

// 当发生HttpRequestException异常时,重试3次 var retryPolicy = Policy.Handle<HttpRequestException>().Retry(3);

有些情况下,如果故障恢复的太慢,我们重试的过快是没有任何任何意义的,这时可以指定重试的时间间隔:

Policy.Handle<HttpRequestException>().WaitAndRetryAsync(5, retryAttempt => TimeSpan.FromSeconds(Math.Pow(2, retryAttempt - 1)));

如上,重试五次,并且重试时间指数级增加。

超时(Timeout)策略

超时是我们比较常见的,比如HttpClient就可以设置超时时间,如果在指定的时间内还没有返回,就触发一个TimeoutException异常,而Polly的超时机制与其类似,只不过超时时触发的是一个TimeoutRejectedException异常。

// 如果30秒种内没有执行完成,就触发`TimeoutRejectedException`异常 Policy.TimeoutAsync(30); // 设置超时回调 Policy.TimeoutAsync(30, onTimeout: (context, timespan, task) => { // do something });

由于超时策略本身就是抛出一个超时异常,所以不需要设置触发条件。

回退(FallBack)策略

回退也称服务降级,用来指定发生故障时的备用方案。

Policy<string>.Handle<HttpRequestException>().FallbackAsync("substitute data", (exception, context) => { // do something });

如上,如果触发HttpRequestException异常时,就返回固定的substitute data。

熔断(Circuit-breaker)策略

断路器用于在服务多次不可用时,快速响应失败,保护系统故障免受过载。

Policy.Handle<HttpRequestException>().Or<TimeoutException>() .CircuitBreakerAsync( // 熔断前允许出现几次错误 exceptionsAllowedBeforeBreaking: 3, // 熔断时间 durationOfBreak: TimeSpan.FromSeconds(100), // 熔断时触发 onBreak: (ex, breakDelay) => { // do something }, // 熔断恢复时触发 onReset: () => { // do something }, // 在熔断时间到了之后触发 onHalfOpen: () => { // do something } );

如上,如果我们的业务代码连续失败3次,就触发熔断(onBreak),就不会再调用我们的业务代码,而是直接抛出BrokenCircuitException异常。当熔断时间(100s)过后,切换为HalfOpen状态,触发onHalfOpen事件,此时会再调用一次我们的业务代码,如果调用成功,则触发onReset事件,并解除熔断,恢复初始状态,否则立即切回熔断状态。

更多策略的用法查看:。

执行

在上面的示例中,我们熟悉了各种策略的定义,那么接下来就是执行它。也就是使用Polly包裹我们的业务代码,Polly会拦截业务代码中的故障,并根据指定的策略进行恢复。

最简单的策略执行方式如下:

var policy = /*策略定义*/; var res = await policy.ExecuteAsync(/*业务代码*/);

如果需要同时指定多个策略,可以使用Policy.Wrap来完成:

Policy.Wrap(retry, breaker, timeout).ExecuteAsync(/*业务代码*/);

其实Warp本质就是多个策略的嵌套执行,使用如下写法效果是一样的:

fallback.Execute(() => waitAndRetry.Execute(() => breaker.Execute(action)));

关于Polly更详细的用法可以查看Polly Github上的https://github.com/App-vNext/Polly/wiki,本文就不再过多介绍。

Polly熔断降级实战

场景:轮询调用服务A和服务B,单次调用时间不得超过1s,调用失败时自动切换到另外一个服务重试一次,如果都失败,进行优雅的降级,返回模拟数据,并在2个服务都多次失败后进行熔断。

首先创建一个ASP.NET Core Console程序,命名为PollyDemo。

然后引入Polly的官方Nuge包:

dotnet add package Polly

在我们首先定义一个超时策略:

var timeoutPolicy = Policy.TimeoutAsync(1, (context, timespan, task) => { Console.WriteLine("It's Timeout, throw TimeoutRejectedException."); return Task.CompletedTask; });

可以根据实际情况来设置超时时间,我这里为了方便测试,就设置为1s。

然后定义重试策略:

var retryPolicy = Policy.Handle<HttpRequestException>().Or<TimeoutException>().Or<TimeoutRejectedException>() .WaitAndRetryAsync( retryCount: 2, sleepDurationProvider: retryAttempt => { var waitSeconds = TimeSpan.FromSeconds(Math.Pow(2, retryAttempt - 1)); Console.WriteLine(DateTime.Now.ToString() + "-Retry:[" + retryAttempt + "], wait " + waitSeconds + "s!"); return waitSeconds; });

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zywpwf.html