熔断降级是一个非常重要的概念,我们先说一下什么是熔断降级,咱们都知道服务发现,一个有问题的服务器没来得急注销过一会就崩溃掉了,那么我们的请求就有可能访问一个已经崩溃的服务器,那么就会请求失败,因为已经game over了。那么这个问题怎么解决呢,你一定要承认,这个问题是无法避免的。没有什么方法说,我拿到的服务器都没有问题,这事是不可能的,所以你要承认你会有机会拿到有问题的服务器。那么熔断降级就是来解决这种问题的。

一.什么是熔断

熔断就像是“保险丝”,当出现梦中状况时,切断服务,从而防止应用程序不断地尝试造成雪崩,这和我们农村的保险丝很像,天气热了防止火灾,那保险丝会自动断开,防止更大的损失。

降级的目的是当某个服务提供者发生故障的时候,向调用方返回一个错误响应替代响应。

比如我们要做一个双11活动的系统,那么比如一个抽奖的模块崩溃,这个时候呢广大客户端疯狂F5,就会导致整个集群雪崩,这个时候我们就应该中断。

还有一栗子,比如说电信和联通,它们在稳定,有也不稳定的时候,那么如果我们用它们的接口,如果电信崩了,我们就是用联通,这种操作的行为就叫做熔断降级。

其使用场景呢,例如,我们要展示商品信息,我们先从数据库读取,读取失败了,我们就通过cache/redis,如果再失败,我们通过固定的Javascript object 来绑定,如果再失败那就返回一个错误的信息。这就是完美的降低了错误。

这种错误的概率就犹如0.01*way³  就是1000次才会出现的概率。那如果是不熔断降级 就是100.以上一些栗子,好好读读即可。

二.Polly介绍

.Net Core 中有一个被.Net基金会认可的k库,可以用来进行熔断降级,主要功能:1.重试(retry);2.断路器(circuit-breaker);3.超时检测(timeout);4.缓存(cache);5.降级(fallback)

官方:https://github.com/app-vnext/polly  nuget: install-package Polly-Version 6.0.1

三.使用

创建项目与安装库,为了稳定还是选择6.0.1吧。

使用Policy的静态方法创建ISyncPolicy实现类对象,创建方法j既有同步方法也有异步方法,根据自己的需求来选择,下面先演示同步方法,异步的方法也类似。

static void Main(string[] args)
{
//handle 当发生argumentException的异常
Policy policy = Policy.Handle<ArgumentException>()
.Fallback(() =>
{
//就干什么事情
Console.WriteLine("出错了");
});
       //有可能异常的时候
policy.Execute(() =>
{
Console.WriteLine("开始执行");
throw new ArgumentException();
Console.WriteLine("执行结束");
});
}

我们运行一下,是如下结果。

但如果书我们故意写一个抛出异常,我们稍微修改一下代码。

policy.Execute(() =>
{
Console.WriteLine("开始执行");
throw new ArgumentException();
Console.WriteLine("执行结束");
});

上面呢,我么捕捉的是ArgumentException异常,那么我们如果是报的其他的错误应该会怎样呢?

policy.Execute(() =>
{
Console.WriteLine("开始执行");
throw new Exception();
Console.WriteLine("执行结束");
});

FallBack中有很多不同的重载,我们可以根据重载获取不同的报错信息,以下是所有的方法。

我们可以简单的去获取一个对象,代码如下:

 Policy policy = Policy.Handle<ArgumentException>()
.Fallback(() =>
{
//就干什么事情
Console.WriteLine("出错了");
},ex=> {
Console.WriteLine(ex.Message);
});
policy.Execute(() =>
{
Console.WriteLine("开始执行");
throw new ArgumentException();
Console.WriteLine("执行结束");
});

因为咱们的业务逻辑啊有可能是带返回值的,也有可能是不带返回值的。那如果你的业务逻辑是带返回值的,你就得用一个Policy带参的泛型来创建,那么这个Policy也是泛型的,在FallBack中也要 提一个替代值,因为毕竟是降级嘛,肯定要有一个值来进行替代。

Policy<string> policy = Policy<string>.Handle<Exception>()
.Fallback(() =>
{
return "降级后的值";
});
string value = policy.Execute(() => {
return "正常值";
});

四.重试处理

polly提供了重试处理机制,那么这个RetryForever()的场景不可能会出现,我也不知道它是处于什么个操作。我觉得这违背了熔断降级,这不可能让它重试的,那么以下就是用法,但是这根本用不着~

还是推荐使用Retry吧。Retry中可以写个int值进去,就是重试的次数,这个还是不错的!

Policy policy = Policy.Handle<Exception>().RetryForever();
policy.Execute(() => {
Console.WriteLine("play task!!");
if (DateTime.Now.Second % 10 != 0)
{
throw new Exception();
}
Console.WriteLine("完成任务!");
});

不过还是有比较正常点的方法,例如WaitAndRetry这个方法,等等再重试。这个很不错!这个方法里的重载非常之多。

Policy policy = Policy.Handle<Exception>().WaitAndRetry(100, i => TimeSpan.FromMinutes(100));
policy.Execute(() => {
Console.WriteLine("play task!!");
if (DateTime.Now.Second % 10 != 0)
{
throw new Exception();
}
Console.WriteLine("完成任务!");
});

五.短路保护Circuit Breaker

短路保护是什么意思呢,这个单词翻译过来就叫做线路切断器,出现N次连续错误,则把“熔断器”(保险丝)熔断,等待一段时间,等待这段时间内如果再Execute则直接抛出BrokenCircuitException异常,根本不会再去尝试调用业务代码。等待时间过去之后,再执行Execute的时候如果又错了(一次就够了),那么继续熔断一段时间,否则就恢复正常。这样就避免一个服务已经不可用了,还是使劲的请求给系统造成更大压力。

这样就避免了一个服务不可用了还在使劲的请求。

 Policy policy = Policy
.Handle<Exception>()
.CircuitBreaker(3, TimeSpan.FromSeconds(5));//连续出错3次之后熔断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);
}

这就像刚才我们说的,我设置了连续3次熔断,那么如果连续3次报错,那么直接不再执行以后的内容,这无疑是非常不错的机制。保证了服务器的性能丢失和不起眼的问题。

六.策略封装与超时处理

策略封装使用的方法是Policy提供的Wrap方法,英译叫做包裹,那么从单词的意思就知道,可以通过策略包裹策略来进行封装,即里面的不行,就走外面的。

Policy policyRetry = Policy.Handle<Exception>()
.Retry(3);
Policy policyFallback = Policy.Handle<Exception>()
.Fallback(() =>
{
Console.WriteLine("降级");
});
Policy policy = policyFallback.Wrap(policyRetry);
policy.Execute(() =>
{
Console.WriteLine("play task!!");
if (DateTime.Now.Second % 10 != 0)
{
throw new Exception();
}
Console.WriteLine("完成任务!");
});

注意这个wrap的包裹顺序的,外在后,内在前。再通过一个超时处理就可以对消耗时间够长的请求进行GG了。

那么你就可以通过超时处理来对我们文章开头的诉说进行一个非常生动形象的通过代码来宣誓。下面说明超时异常的说明

Policy policytimeout = Policy.Timeout(3, TimeoutStrategy.Pessimistic);
Policy policyFallBack = Policy.Handle<TimeoutRejectedException>()
.Fallback(() =>
{
Console.WriteLine("熔断降级");
});
Policy policy = policyFallBack.Wrap(policytimeout);
policy.Execute(() =>
{
Console.WriteLine("完成任务");
Thread.Sleep(5000);
Console.WriteLine("完成任务");
});
Console.ReadKey();

这玩腻的用途不过就是:请求网络接口,避免接口长期没有响应造成系统卡死。

七.Polly的异步

     Test1().Wait(); //调用

        static async Task Test1()
{ 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(20, 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("https://www.cnblogs.com/images/logo_small.gif");
Console.WriteLine("完成任务");
return result;
});
Console.WriteLine("bytes长度" + bytes.Length);
}

使用Polly的异步,那么所有的方法都必须是异步,除了Handle方法,因为handle就不需要异步,也没有返回值。通过异步呢,所有的重载方法都构造了一遍,还是可以继续用的。那么这段代码的意思是,通过异步的方式如果我通过httpclient获取某站点的图片的base值,如果在此期间我定义了一个policy,抓住一个异常,如果说两秒之内还没有反应我就超时。直接终止。测试的时候 你可以把值 改变下。

八.最后

相信你跟着我写到现在,已经感到这代码已经非常恶心了,代码中有非常多冗余的代码,近期会使用AspectCore这个AOP框架,听别人说这个库不错,这和Spring cloud的Hystrix差不多。就这样了,再见,喜欢点个推荐!

三分钟学会.NET微服务之Polly的更多相关文章

  1. 中小研发团队架构实践之生产环境诊断工具WinDbg 三分钟学会.NET微服务之Polly 使用.Net Core+IView+Vue集成上传图片功能 Fiddler原理~知多少? ABP框架(asp.net core 2.X+Vue)模板项目学习之路(一) C#程序中设置全局代理(Global Proxy) WCF 4.0 使用说明 如何在IIS上发布,并能正常访问

    中小研发团队架构实践之生产环境诊断工具WinDbg 生产环境偶尔会出现一些异常问题,WinDbg或GDB是解决此类问题的利器.调试工具WinDbg如同医生的听诊器,是系统生病时做问题诊断的逆向分析工具 ...

  2. 微服务之Polly熔断策略

    NET Core 微服务之Polly熔断策略 紧接着上一篇说,咱们继续介绍Polly这个类库 熔断策略(Circuit-breaker) 如果调用某个目标服务出现过多超时.异常等情况,可以采取一定时间 ...

  3. 三分钟学会@Autowired@Qualifier@Primary注解

    三分钟学会@Autowired@Qualifier@Primary注解 2018.10.08 20:24 154浏览 今天主要简单的跟大家介绍一下spring自动装配相关的@Autowired,@Qu ...

  4. 三分钟学会使用Derby数据库

    Derby数据库是一个纯用Java实现的内存数据库,属于Apache的一个开源项目.由于是用Java实现的,所以可以在任何平台上运行:另外一个特点是体积小,免安装,java1.6开始集成了derby数 ...

  5. [转]三分钟学会.NET Core Jwt 策略授权认证

    [转]三分钟学会.NET Core Jwt 策略授权认证 一.前言# 大家好我又回来了,前几天讲过一个关于Jwt的身份验证最简单的案例,但是功能还是不够强大,不适用于真正的项目,是的,在真正面对复杂而 ...

  6. 第三十九章 微服务CICD(1)- gitlab搭建与使用(docker版)

    一.下载docker镜像 前提:docker引擎已经安装好. docker pull gitlab/gitlab-ce gitlab是8.13.1版本. 二.启动应用 docker run -d -h ...

  7. .NET Core 微服务之Polly重试策略

    接着上一篇说,正好也是最近项目里用到了,正好拿过来整理一下,园子里也有一些文章介绍比我详细. 简单介绍一下绍轻量的故障处理库 Polly  Polly是一个.NET弹性和瞬态故障处理库 允许我们以非常 ...

  8. SpringCloud学习笔记(三):Rest微服务构建案例工程模块

    需要具备的知识 1 springmvc+mybatis+mysql 2 Consumer消费者(Client)通过REST调用Provider提供者(Server)提供的服务 3 Maven的分包分模 ...

  9. docker微服务部署之:三,搭建Zuul微服务项目

    docker微服务部署之:二.搭建文章微服务项目 一.新增demo_eureka模块,并编写代码 右键demo_parent->new->Module->Maven,选择Module ...

随机推荐

  1. Maven常识

    maven下面通常有四个文件夹: src/main/java -- 用来存放业务代码 src/test/java -- 用来存放测试代码 另有两个名为resource的文件夹,通常用来放置前两个文件夹 ...

  2. 在MFC中怎么获得Excel文档中已经使用了的行数和列数

    _Worksheet ws;Range range; range = ws.GetUsedRange();//获得Worksheet已使用的范围range = range.GetRows();   / ...

  3. Ceilometer + Aodh + Gnocchi 介绍

    一.  Ceilometer 1.    概述 Openstack ceilometer主要用于监控虚拟机.服务(glance.image.network等)和事件.虚拟机的监控项主要包括CPU.磁盘 ...

  4. Uber无人驾驶致命车祸翻案:6秒前已侦测到死者

    此前有消息称,今年三月 Uber 无人驾驶汽车致命车祸是软件失误导致的.现在,美国运输安全委员会的事故初步调查报告给出了不同的说法. 从图中可见,黄色线以米为单位显示,橙色线显示了地图线路的中心,紫色 ...

  5. monkey-----停止正在测试的monkey

    第一步:adb   shell ps | grep monkey:查找到正在测试的monkey包名   第二步:kill   pid:删除查找出的monkey进程   以上完美的停止monkey测试

  6. MYSQL—— 基础入门,select 查询涉及到的关键字组合详解(进阶篇)

    SELECT查询组合使用的关键字很多,首先将最简单常用的关键字进行区分及使用,后续再继续补充............ 以下所有的关键字组合使用,主要以两个表students与students_scor ...

  7. TensorFlow之RNN:堆叠RNN、LSTM、GRU及双向LSTM

    RNN(Recurrent Neural Networks,循环神经网络)是一种具有短期记忆能力的神经网络模型,可以处理任意长度的序列,在自然语言处理中的应用非常广泛,比如机器翻译.文本生成.问答系统 ...

  8. shell简明教程

    shell的格式 shell可以在直接在命令行下输入,也可以保存成shell脚本文件运行.当命令简单并且不需要重复使用,在命令行输入直接执行即可,否则就写成脚本.shell脚本默认文件扩展名为.sh. ...

  9. Java的自定义注解使用实例

    概念 Java有五个元注解,自动继承java.lang.annotation.Annotation. 什么是元注解,可以理解为其他普通注解进行解释说明 @Target  该注解的使用范围,限定应用场景 ...

  10. vue.js框架原理浅析

    vue.js是一个非常优秀的前端开发框架,不是我说的,大家都知道. 首先我现在的能力,独立阅读源码还是有很大压力的,所幸vue写的很规范,通过方法名基本可以略知一二,里面的原理不懂的地方多方面查找资料 ...