熔断降级是一个非常重要的概念,我们先说一下什么是熔断降级,咱们都知道服务发现,一个有问题的服务器没来得急注销过一会就崩溃掉了,那么我们的请求就有可能访问一个已经崩溃的服务器,那么就会请求失败,因为已经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. Oracle的dual表是个什么东东

    dual是一个虚拟表,用来构成select的语法规则,oracle保证dual里面永远只有一条记录.我们可以用它来做很多事情,如下: 1.查看当前用户,可以在 SQL Plus中执行下面语句 sele ...

  2. BZOJ_2738_矩阵乘法_整体二分

    BZOJ_2738_矩阵乘法_整体二分 Description 给你一个N*N的矩阵,不用算矩阵乘法,但是每次询问一个子矩形的第K小数. Input 第一行两个数N,Q,表示矩阵大小和询问组数: 接下 ...

  3. 从MVC和三层架构说到SSH整合开发

    相信很多人都认同JavaWeb开发是遵从MVC开发模式的,遵从三层架构进行开发的,是的,大家都这么认同.但是相信大家都会有过这样一个疑问,if(MVC三层模式==三层架构思想)out.println( ...

  4. CentOS7 配置SVN服务器

    也可以参考这里:https://jingyan.baidu.com/article/148a1921d84be34d71c3b18f.html 1.安装svn yum install -y subve ...

  5. HTTP 和 WebSocket的区别

    有关http和WebSocket 的区别网上有很多的质料. 个人在此仅仅是记录以下自己的学习心得,自己的理解. 1. http协议是用在应用层的协议,他是基于tcp协议的,http协议建立链接也必须要 ...

  6. python——绘制二元高斯分布的三维图像,

    在对数据进行可视化的过程中,可能经常需要对数据进行三维绘图,在python中进行三维绘图其实是比较简单的,下面我们将给出一个二元高斯分布的三维图像案例,并且给出相关函数的参数. 通常,我们绘制三维图像 ...

  7. spark集群搭建整理之解决亿级人群标签问题

    最近在做一个人群标签的项目,也就是根据客户的一些交易行为自动给客户打标签,而这些标签更有利于我们做商品推荐,目前打上标签的数据已达5亿+, 用户量大概1亿+,项目需求就是根据各种组合条件寻找标签和人群 ...

  8. .NET 平台上C#语言的基本技术点

    第一次用画图3D画的知识点,有点丑..........开始Csharp之路

  9. [PHP] 使用反射实现的控制反转

    搬家进程中反射实现控制反转,样做的好处是可以通过配置项动态的控制下面那个类的属性 1.$this->getObject($class, $config->getConfig('param' ...

  10. Java-每日编程练习题①

    1.输出打印一个九九乘法表 代码如下,很简单的一个for的嵌套循环即可实现 /** * 输出9*9口诀. * * @author ChenZX * */ public class Test01 { p ...