一、 什么是熔断降级

熔断就是“保险丝”。当出现某些状况时,切断服务,从而防止应用程序不断地尝试执行可能会失败的操作给系统造成“雪崩”,或者大量的超时等待导致系统卡死。

降级的目的是当某个服务提供者发生故障的时候,向调用方返回一个错误响应或者替代响应。举例子:调用联通接口服务器发送短信失败之后,改用移动短信服务器发送,如果移动短信服务器也失败,则改用电信短信服务器,如果还失败,则返回“失败”响应;在从推荐商品服务器加载数据的时候,如果失败,则改用从缓存中加载,如果缓存中也加载失败,则返回一些本地替代数据。

二、 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("完成任务");
});

执行结果:

(5).NET CORE微服务 Micro-Service ---- 熔断降级(Polly)的更多相关文章

  1. Spring Cloud微服务如何实现熔断降级?

    熔断限流概述 在基于Spring Cloud的微服务架构体系下,按照系统功能边界的不同划分,原先大而全的系统会被拆分为多个不同的微服务,而相应的微服务会提供一组功能关联的服务接口,并向系统中的其他微服 ...

  2. .NET Core微服务之基于Polly+AspectCore实现熔断与降级机制

    Tip: 此篇已加入.NET Core微服务基础系列文章索引 一.熔断.降级与AOP 1.1 啥是熔断? 在广义的解释中,熔断主要是指为控制股票.期货或其他金融衍生产品的交易风险,为其单日价格波动幅度 ...

  3. .NET Core微服务之基于Steeltoe使用Hystrix熔断保护与监控

    Tip: 此篇已加入.NET Core微服务基础系列文章索引 =>  Steeltoe目录快速导航: 1. 基于Steeltoe使用Spring Cloud Eureka 2. 基于Steelt ...

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

    当我们从单体架构迁移到微服务模式时,其中一个比较大的变化就是模块(业务,服务等)间的调用方式.在以前,一个业务流程的执行在一个进程中就完成了,但是在微服务模式下可能会分散到2到10个,甚至更多的机器( ...

  5. (5)学习笔记 ) ASP.NET CORE微服务 Micro-Service ---- 熔断降级(Polly)

    一. 什么是熔断降级 熔断就是“保险丝”.当出现某些状况时,切断服务,从而防止应用程序不断地尝试执行可能会失败的操作给系统造成“雪崩”,或者大量的超时等待导致系统卡死. 降级的目的是当某个服务提供者发 ...

  6. .NET Core微服务之基于Consul实现服务治理

    Tip: 此篇已加入.NET Core微服务基础系列文章索引 一.Consul基础介绍 Consul是HashiCorp公司推出的开源工具,用于实现分布式系统的服务发现与配置.与其他分布式服务注册与发 ...

  7. .NET Core微服务之基于Consul实现服务治理(续)

    Tip: 此篇已加入.NET Core微服务基础系列文章索引 上一篇发布之后,很多人点赞和评论,不胜惶恐,这一篇把上一篇没有弄到的东西补一下,也算是给各位前来询问的朋友的一些回复吧. 一.Consul ...

  8. .NET Core微服务之基于Ocelot实现API网关服务

    Tip: 此篇已加入.NET Core微服务基础系列文章索引 一.啥是API网关? API 网关一般放到微服务的最前端,并且要让API 网关变成由应用所发起的每个请求的入口.这样就可以明显的简化客户端 ...

  9. .NET Core微服务之基于Ocelot实现API网关服务(续)

    Tip: 此篇已加入.NET Core微服务基础系列文章索引 一.负载均衡与请求缓存 1.1 负载均衡 为了验证负载均衡,这里我们配置了两个Consul Client节点,其中ClientServic ...

  10. .NET Core微服务之基于Ocelot+IdentityServer实现统一验证与授权

    Tip: 此篇已加入.NET Core微服务基础系列文章索引 一.案例结构总览 这里,假设我们有两个客户端(一个Web网站,一个移动App),他们要使用系统,需要通过API网关(这里API网关始终作为 ...

随机推荐

  1. boost.lexical_cast 学习

    1,字符串 到 数值类型的转换 2,数值 到 字符串的转换 3,异常处理情况 4,boost::lexical_cast 的原型: template<typename Target, typen ...

  2. struts2框架之请求参数(参考第二天学习笔记)

    获取请求参数 请求参数:表单中的数据,或者是超链接中的数据. 1. 得到request,再通过request来获取.2. 属性驱动 在Action中提供与表单字段名称相同的属性即可. 而一个名为par ...

  3. codeforces 161D Distance in Tree 树上点分治

    链接:https://codeforces.com/contest/161/problem/D 题意:给一个树,求距离恰好为$k$的点对是多少 题解:对于一个树,距离为$k$的点对要么经过根节点,要么 ...

  4. T-SQL LIKE子句 模糊查询

    MS SQL Server LIKE子句用于使用通配符运算符将值与类似值进行比较. 有两个通配符与LIKE运算符结合使用: 百分号(%) 下划线(_) 百分号表示零个,一个或多个字符. 下划线表示单个 ...

  5. 下载chrome插件和离线安装CRX文件的方法

    自从chrome网上应用店出来后无法下载插件,必须在线安装,安装后又自动把CRX删除,而且是那么的迅速...以下是下载离线插件包的方法:第一步: 每个Google Chrome扩展都有一个固定的ID, ...

  6. 51nod--1298 (计算几何基础)

    题目: 1298 圆与三角形 题目来源: HackerRank 基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题 收藏 关注 给出圆的圆心和半径,以及三角形的三个顶点,问圆 ...

  7. Idea 调试快捷键

    F9            resume programe 恢复程序 Alt+F10       show execution point 显示执行断点 F8            Step Over ...

  8. js——this

    每个函数的this是在调用时绑定的,完全取决于函数的调用位置 1. 绑定规则总结 一般情况下,按下列顺序从下至上来判断this的绑定对象(绑定的优先级从下至上递减) 默认:在严格模式下绑定到undef ...

  9. iOS -- Effective Objective-C 阅读笔记 (1)

    1: 在类的头文件中尽量 少 的引用其他头文件,尽量用 @class xxxxxx; 理解: 当你创建了一个 A 类,这个类又 需要具有 B 类的实例, 你可以直接为 A 类添加 B 类类型的 属性, ...

  10. Vue.js结合vue-router和webpack编写单页路由项目

    一.前提 1. 安装了node.js. 2. 安装了npm. 3. 检查是否安装成功: 打开cmd,输入node,没有报“node不是内部或外部命令”表示安装成功node.js. 打开cmd,输入np ...