首页 > Python基础教程 >
-
C#教程之polly微服务故障处理库
熔断、降级:
熔断:熔断就是我们常说的“保险丝”,意为当服务出现某些状况时,切断服务,从而防止应用程序不断地常识执行可能会失败的操作造成系统的“雪崩”,或者大量的超时等待导致系统卡死等情况,很多地方也将其成为“过载保护”。
降级:降级的目的就是当某个服务提供者发生故障的时候,向调用方返回一个替代响应或者错误响应。
介绍:
POLLY是一个.NET回弹和瞬态故障处理库,它允许开发人员以流畅和线程安全的方式表达诸如重试、断路器、超时、隔板隔离和回退等策略。github官方解释嘿嘿。
Polly以.NET Standard 1.1(覆盖范围:.NET Framework 4.5-4.6.1,.NET Core 1.0,Mono,Xamarin,UWP,WP8.1 +)
.NET Standard 2.0+(覆盖范围:.NET Framework 4.6.1, .NET Core 2.0+以及后来的Mono,Xamarin和UWP目标)
安装:
首先当然是创建一个控制台项目,然后通过NuGet安装:
Install-Package Polly
出现以上界面就说明你已经安装了最新的版本到你的项目;
策略介绍:
polly通过官方介绍我们可以知道有7种恢复策略,先不管会不会,先列出来再说哈哈:
重试策略(Retry):许多故障是短暂的,并且在短暂的延迟后可能会自我纠正。允许我们做的是能够自动配置重试机制
断路器(Circuit-breaker):当一个系统严重挣扎时,快速失败优于让用户/呼叫者等待。 说白了就是应该优先直接返回失败,而不是一直让用户等待。保护故障系统免受过载可以帮助恢复。
超时(Timeout):超时策略针对的前置条件是超过一定的等待时间,想要得到成功的结果是不可能的,保证调用者不必等待超时。
隔板隔离(Bulkhead Isolation):隔板隔离针对的前置条件是当进程出现故障时,多个失败一直在主机中对资源(例如线程/ CPU)一直占用。下游系统故障也可能导致上游失败。这两个风险都将造成严重的后果。都说一粒老鼠子屎搅浑一锅粥,而Polly则将受管制的操作限制在固定的资源池中,免其他资源受其影响。
缓存(Cache):就是一些请求,会把数据缓存起来,然后在持续一段时间内,直接从缓存中取。
回退(Fallback):操作仍然会失败,也就是说当发生这样的事情时我们打算做什么。也就是说定义失败返回操作。我们在使用时就是所说的降级。
策略包装(PolicyWrap):不同的故障需要不同的策略 弹性意味着使用组合。
使用步骤:
polly一般分为三步进行:
-
定义条件: 定义你要处理的 错误异常/返回结果
-
定义处理方式 : 重试,熔断,回退
-
执行
定义条件:
.Handle<ExceptionType>():限定条件的单个异常Policy;
.Handle<ExceptionType>(ex => ex.Number == 10):具有条件的单个异常类型。
.Handle<HttpRequestException>()
.Or<OperationCanceledException>():多个异常类型,当然他也可以变成具有条件的多个异常类型,类似于单个操作。
定义返回结果的条件:
.HandleResult<HttpResponseMessage>(r => r.StatusCode == HttpStatusCode.NotFound):用条件处理返回值,处理单个返回值。
.HandleResult<HttpResponseMessage>(r => r.StatusCode == HttpStatusCode.InternalServerError)
.OrResult<HttpResponseMessage>(r => r.StatusCode == HttpStatusCode.BadGateway):处理多个返回值。
指定策略(重试):
.Retry():重试一次。
.Retry(3):重试三次,修改数值即可定义自己想使用的次数。
.Retry(3, (exception, retryCount) =>
{
// do something
}):重试多次,在每次重试都执行一个操作,参数为:当前异常和重试计数。
.Retry(3, (exception, retryCount, context) =>
{
// do something
}):重试多次,在每次重试都执行一个操作,参数为:当前异常,重试计数和上下文
.RetryForever():永远重试直到成功,同时也也有重试的相同扩展,可以写参数。
.WaitAndRetry(new[]
{
TimeSpan.FromSeconds(1),
TimeSpan.FromSeconds(2),
TimeSpan.FromSeconds(3)
}):等待并重试,就是在每个重试的时候需要等待指定的执行时间,同样有相同扩展,可以在每个重试调用一个操作。
.WaitAndRetryForever(retryAttempt =>
TimeSpan.FromSeconds(Math.Pow(2, retryAttempt))
):等待和重试永远(直到成功)
指定策略(熔断):
.CircuitBreaker(2, TimeSpan.FromMinutes(1)):在指定数量的连续异常之后中断开。这里就不做过多解释了。
指定策略(降级):回退
.Fallback<UserAvatar>(UserAvatar.Blank):如果执行错误,则提供替代值,就是出现错误,定义一个返回值给他
.Fallback<UserAvatar>(() => UserAvatar.GetRandomAvatar()) :定义一个方法给他,该方法代替提供值。
执行:
.Execute(() => DoSomething()):执行一项方法
执行通过任意上下文数据的操作:
var policy = Policy .Handle<SomeExceptionType>() .Retry(3, (exception, retryCount, context) => { var methodThatRaisedException = context["methodName"]; Log(exception, methodThatRaisedException); }); policy.Execute( () => DoSomething(), new Dictionary<string, object>() {{ "methodName", "some method" }} );
使用示例:
降级的使用代码:
#region 降级 public static void Downgrade() { //降级处理程序 ISyncPolicy policy = Policy.Handle<ArgumentException>() .Fallback(() => { Console.WriteLine("降级给的返回值结果"); }); //运行程序 policy.Execute(() => { Console.WriteLine("任务开始"); throw new ArgumentException("降级任务出错,马上要降级了"); Console.WriteLine("任务结束"); }); } #endregion
运行结果:
重试机制的代码:
出错后重复3次。
#region 重试机制 public static void Retry() { //配置重试次数 ISyncPolicy policy = Policy.Handle<Exception>().Retry(3); try { policy.Execute(() => { Console.WriteLine("任务开始"); if (DateTime.Now.Second % 10 != 0) { throw new Exception("任务出错了,开始重试"); } Console.WriteLine("任务结束"); }); } catch (Exception ex) { Console.WriteLine("异常结果 : " + ex.Message); } } #endregion
运行结果:
熔断机制代码:
但出现错误连续三次后,等待20秒后进行
#region 熔断机制 public static void Fusing() { Action<Exception, TimeSpan> onBreak = (exception, timespan) => { Console.WriteLine("1"); }; Action onReset = () => { Console.WriteLine("2"); }; ISyncPolicy policy = Policy.Handle<Exception>().CircuitBreaker(3, TimeSpan.FromSeconds(20), onBreak, onReset); while (true) { try { policy.Execute(() => { Console.WriteLine("任务开始"); throw new Exception("出错了"); Console.WriteLine("任务结束"); }); } catch (Exception ex) { Console.WriteLine("---------------异常结果-------------- : " + ex.Message + "时间:" + DateTime.Now); } System.Threading.Thread.Sleep(5000); } } #endregion
运行结果:
混合示例(重试+降级)代码:
出错重试三次后第四次进行降级处理:主要是warp方法来实现的,特别说明warp方法是:最外面(在左边)到最里面(右边)的策略。也就是说从右向左执行方法;
#region 重试+降级 public static void RetryDowngrade() { try { //降级处理程序 ISyncPolicy policy = Policy.Handle<Exception>() .Fallback(() => { Console.WriteLine("降级成功"); }); //配置重试次数 ISyncPolicy policy2 = Policy.Handle<Exception>().Retry(3, (exception, retryCount, context) => { Console.WriteLine(retryCount); }); //合并 ISyncPolicy mainPolicy = Policy.Wrap(policy, policy2); mainPolicy.Execute(() => { Console.WriteLine("任务开始"); throw new Exception("出错了"); Console.WriteLine("任务结束"); }); } catch (Exception ex) { Console.WriteLine("异常结果 : " + ex.Message); } } #endregion
运行结果: