(5)学习笔记 ) ASP.NET CORE微服务 Micro-Service ---- 熔断降级(Polly)
一、 什么是熔断降级
熔断就是“保险丝”。当出现某些状况时,切断服务,从而防止应用程序不断地尝试执行可能会失败的操作给系统造成“雪崩”,或者大量的超时等待导致系统卡死。
降级的目的是当某个服务提供者发生故障的时候,向调用方返回一个错误响应或者替代响应。举例子:调用联通接口服务器发送短信失败之后,改用移动短信服务器发送,如果移动短信服务器也失败,则改用电信短信服务器,如果还失败,则返回“失败”响应;在从推荐商品服务器加载数据的时候,如果失败,则改用从缓存中加载,如果缓存中也加载失败,则返回一些本地替代数据。
二、 Polly 简介
.Net Core 中有一个被.Net 基金会认可的库 Polly,可以用来简化熔断降级的处理。主要功能:重试(Retry);断路器(Circuit-breaker);超时检测(Timeout);缓存(Cache);降级(FallBack);
官网:https://github.com/App-vNext/Polly
介绍文章:https://www.cnblogs.com/CreateMyself/p/7589397.html
Nuget安装指令:Install-Package Polly -Version 6.0.1
Polly 的策略由“故障”和“动作”两部分组成,“故障”包括异常、超时、返回值错误等情况,“动作”包括 降级(FallBack)、重试(Retry)、熔断(Circuit-breaker)等。
策略用来执行可能会有有故障的业务代码,当业务代码出现“故障”中情况的时候就执行“动作”。
由于实际业务代码中故障情况很难重现出来,所以 Polly 这一些都是用一些无意义的代码模拟出来。
Polly 也支持请求缓存“数据不变化则不重复自行代码”,但是和新版本兼容不好,而且功能局限性很大,因此这里不讲。
由于调试器存在,看不清楚 Polly 的执行过程,因此本节都用【开始执行(不调试)】
三、Polly简单使用
使用Policy的静态方法创建ISyncPolicy实现类对象,创建方法既有同步方法也有异步方法,根据自己的需要选择。下面先演示同步的,异步的用法类似。
举例:当发生ArgumentException异常的时候,执行Fallback代码。
Policy policy = Policy .Handle<ArgumentException>() //故障 .Fallback(() =>//动作 { Console.WriteLine("执行出错"); }); policy.Execute(() => {//在策略中执行业务代码 //这里是可能会产生问题的业务系统代码 Console.WriteLine("开始任务"); throw new ArgumentException("Hello world!"); Console.WriteLine("完成任务"); }); Console.ReadKey();
如果没有被Handle处理的异常,则会导致未处理异常被抛出。
还可以用Fallback的其他重载获取异常信息:
Policy policy = Policy .Handle<ArgumentException>() //故障 .Fallback(() =>//动作 { Console.WriteLine("执行出错"); },ex=> { Console.WriteLine(ex); }); policy.Execute(() => { //在策略中执行业务代码 //这里是可能会产生问题的业务系统代码 Console.WriteLine("开始任务1"); throw new ArgumentException("Hello1 world!"); Console.WriteLine("完成任务"); });
如果Execute中的代码是带返回值的,那么只要使用带泛型的Policy<T>类即可:
Policy<string> policy = Policy<string> .Handle<Exception>() //故障 .Fallback(() =>//动作 { Console.WriteLine("执行出错");
return "降级的值"; }); string value = policy.Execute(() => { Console.WriteLine("开始任务");
throw new Exception("Hello world!");
Console.WriteLine("完成任务");
return "正常的值"; }); Console.WriteLine("返回值:"+value);
FallBack的重载方法也非常多,有的异常可以直接提供降级后的值。
(*)异常中还可以通过lambda表达式对异常判断“满足***条件的异常我才处理”,简单看看试试重载即可。还可以多个Or处理各种不同的异常。
(*)还可以用HandleResult等判断返回值进行故障判断等,我感觉没太大必要。
四、重试处理
Policy policy = Policy .Handle<Exception>() .RetryForever(); policy.Execute(() => {
Console.WriteLine("开始任务"); if (DateTime.Now.Second % 10 != 0) { throw new Exception("出错"); } Console.WriteLine("完成任务"); });
RetryForever()是一直重试直到成功
Retry()是重试最多一次;
Retry(n) 是重试最多n次;
WaitAndRetry()可以实现“如果出错等待100ms再试还不行再等150ms秒。。。。”,重载方法很多,不再一一介绍。还有WaitAndRetryForever。
五、 短路保护 Circuit Breaker
出现N次连续错误,则把“熔断器”(保险丝)熔断,等待一段时间,等待这段时间内如果再Execute 则直接抛出BrokenCircuitException异常,根本不会再去尝试调用业务代码。等待时间过去之后,再执行Execute的时候如果又错了(一次就够了),那么继续熔断一段时间,否则就恢复正常。
这样就避免一个服务已经不可用了,还是使劲的请求给系统造成更大压力。
Policy policy = Policy .Handle<Exception>() .CircuitBreaker(6,TimeSpan.FromSeconds(5));//连续出错6次之后熔断5秒(不会再去尝试执行业务代码)。 while(true) { Console.WriteLine("开始Execute"); try { policy.Execute(() => { Console.WriteLine("开始任务"); throw new Exception("出错"); Console.WriteLine("完成任务"); }); } catch(Exception ex) { Console.WriteLine("execute出错"+ex); } Thread.Sleep(500); }
其计数的范围是policy对象,所以如果想整个服务器全局对于一段代码做短路保护,则需要共用一个policy对象。
六、策略封装,包裹Warp
可以把多个ISyncPolicy合并到一起执行:
policy3= policy1.Wrap(policy2);
执行policy3就会把policy1、policy2封装到一起执行。
Policy的静态方法Wrap可以把更多的policy一起封装:
policy9=Policy.Wrap(policy1, policy2, policy3, policy4, policy5);
七、超时处理
这些处理不能简单的链式调用,要用到Wrap。例如下面实现“出现异常则重试三次,如果还出错就FallBack”这样是不行的
Policy policy = Policy.Handle<Exception>().Retry(3).Fallback(()=> { Console.WriteLine("执行出错"); });//这样不行,系统会直接报错
注意Wrap是有包裹顺序的,内层的故障如果没有被处理则会抛出到外层。
下面代码实现了“出现异常则重试三次,如果还出错就FallBack”
Policy policyRetry = Policy.Handle<Exception>().Retry(3); //出现异常重试三次 Policy policyFallback = Policy .Handle<Exception>() .Fallback(()=> { Console.WriteLine("降级"); }); //Wrap:包裹。policyRetry在里面,policyFallback裹在外面。 //如果里面出现了故障,则把故障抛出来给外面 Policy policy = policyFallback.Wrap(policyRetry); policy.Execute(()=> { Console.WriteLine("开始任务"); if (DateTime.Now.Second % 10 != 0) { throw new Exception("出错"); } Console.WriteLine("完成任务"); });
运行结果:
Timeout是定义超时故障,如果超时会抛出TimeoutRejectedException异常。
Policy policy = Policy.Timeout(3, TimeoutStrategy.Pessimistic);// 创建一个3秒钟(注意单位)的超时策略。
Timeout生成的Policy要和其他Policy一起Wrap使用。
超时策略一般不能直接用,而是和其他封装到一起用:
Policy policy = Policy .Handle<TimeoutRejectedException>() //定义所处理的故障 .Fallback(() => { Console.WriteLine("降级"); }); policy = policy.Wrap(Policy.Timeout(2,TimeoutStrategy.Pessimistic)); policy.Execute(()=> { Console.WriteLine("开始任务"); Thread.Sleep(5000); Console.WriteLine("完成任务"); });
执行结果:
上面的代码就是如果执行超过2秒钟,则直接Fallback。 这个的用途:请求网络接口,避免接口长期没有响应造成系统卡死。
八、Polly 的异步用法
所有方法都用Async方法即可,Handle由于只是定义异常,所以不需要异常方法:
带返回值的例子:
Policy<byte[]> policy = Policy<byte[]> .Handle<Exception>() .FallbackAsync(async c => { Console.WriteLine("降级"); return new byte[0]; },async r=> { Console.WriteLine(r.Exception); }); policy = policy.WrapAsync(
Policy.TimeoutAsync(2, TimeoutStrategy.Pessimistic, async(context, timespan, task) => { Console.WriteLine("timeout"); })
); var bytes = await policy.ExecuteAsync(async () => { Console.WriteLine("开始任务"); HttpClient httpClient = new HttpClient(); var result = await httpClient.GetByteArrayAsync("http://static.rupeng.com/upload/chatimage/20183/07EB793A4C247A654B31B4D14EC64BCA.png"); Console.WriteLine("完成任务"); return result; }); Console.WriteLine("bytes长度"+bytes.Length);
执行结果:
没返回值的例子:
Policy policy = Policy .Handle<Exception>() .FallbackAsync(async c => { Console.WriteLine("降级"); },async ex=> {//对于没有返回值的,这个参数直接是异常 Console.WriteLine(ex); }); policy = policy.WrapAsync(Policy.TimeoutAsync(3, TimeoutStrategy.Pessimistic, async(context, timespan, task) => { Console.WriteLine("timeout"); })); await policy.ExecuteAsync(async () => { Console.WriteLine("开始任务"); await Task.Delay(5000);//注意不能用Thread.Sleep(5000); Console.WriteLine("完成任务"); });
执行结果:
注:此文章是我看杨中科老师的.Net Core微服务第二版和.Net Core微服务第二版课件整理出来的
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
使用 vue-cli + element-ui 快速搭建项目
一、前言 vue2.0的到来,凭借这其简单易学、完善的API中文文档、丰富的生态系统,成为国内目前十分受欢迎的前端MVVM框架,element-ui是基于vue2.0的ui框架,由饿了么团队开发维护的,目前是vue的ui库中最受欢迎的一个框架 element-ui官网vue专题网站 在vue专题中可以看到各个ui框架的受欢迎程度 二、代码操作 使用vue-cli + element-ui有两种方式 方案一: ①先使用vue-cli搭建好项目, ②再使用npm install对应的模块、插件, ③再去webpack.conf.js中进行配置各种文件的加载器, ④再去.babelrc中配置插件 如果项目还没开始编写,就不要使用方案一了,如果项目已经启动了一阵子了,那就得按以上要点每一步都得处理好,稍有不慎,就报错了,这里介绍一下方案二,就是使用 element-ui 提供的一个模板 方案二: ① 使用 git 命令git clone https://github.com/ElementUI/element-starter.git下载官方提供的模板, ② 使用cnpm intsall下载依赖...
- 下一篇
使用 Dubbo 对遗留单体系统进行微服务改造
Credit:Justin Kenneth Rowley. You can find the original photo atflickr. The microservices style of architecture highlights rising abstractions in the developer world because of containerization and the emphasis on low coupling, offering a high level of operational isolation. Developers can think of a container as a self-contained process and the PaaS as the common de
相关文章
文章评论
共有0条评论来说两句吧...