三分钟学会.NET微服务之Polly

熔断降级是一个非常重要的概念,我们先说一下什么是熔断降级,咱们都知道服务发现,一个有问题的服务器没来得急注销过一会就崩溃掉了,那么我们的请求就有可能访问一个已经崩溃的服务器,那么就会请求失败,因为已经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的更多相关文章
- 中小研发团队架构实践之生产环境诊断工具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如同医生的听诊器,是系统生病时做问题诊断的逆向分析工具 ...
- 微服务之Polly熔断策略
NET Core 微服务之Polly熔断策略 紧接着上一篇说,咱们继续介绍Polly这个类库 熔断策略(Circuit-breaker) 如果调用某个目标服务出现过多超时.异常等情况,可以采取一定时间 ...
- 三分钟学会@Autowired@Qualifier@Primary注解
三分钟学会@Autowired@Qualifier@Primary注解 2018.10.08 20:24 154浏览 今天主要简单的跟大家介绍一下spring自动装配相关的@Autowired,@Qu ...
- 三分钟学会使用Derby数据库
Derby数据库是一个纯用Java实现的内存数据库,属于Apache的一个开源项目.由于是用Java实现的,所以可以在任何平台上运行:另外一个特点是体积小,免安装,java1.6开始集成了derby数 ...
- [转]三分钟学会.NET Core Jwt 策略授权认证
[转]三分钟学会.NET Core Jwt 策略授权认证 一.前言# 大家好我又回来了,前几天讲过一个关于Jwt的身份验证最简单的案例,但是功能还是不够强大,不适用于真正的项目,是的,在真正面对复杂而 ...
- 第三十九章 微服务CICD(1)- gitlab搭建与使用(docker版)
一.下载docker镜像 前提:docker引擎已经安装好. docker pull gitlab/gitlab-ce gitlab是8.13.1版本. 二.启动应用 docker run -d -h ...
- .NET Core 微服务之Polly重试策略
接着上一篇说,正好也是最近项目里用到了,正好拿过来整理一下,园子里也有一些文章介绍比我详细. 简单介绍一下绍轻量的故障处理库 Polly Polly是一个.NET弹性和瞬态故障处理库 允许我们以非常 ...
- SpringCloud学习笔记(三):Rest微服务构建案例工程模块
需要具备的知识 1 springmvc+mybatis+mysql 2 Consumer消费者(Client)通过REST调用Provider提供者(Server)提供的服务 3 Maven的分包分模 ...
- docker微服务部署之:三,搭建Zuul微服务项目
docker微服务部署之:二.搭建文章微服务项目 一.新增demo_eureka模块,并编写代码 右键demo_parent->new->Module->Maven,选择Module ...
随机推荐
- 8. 使用ueditor添加文章
ueditor是一个很好用的html编辑器,不仅提供了格式化编辑文本的功能,还提供了自动上传图片的功能,现在就使用该编辑器来实现博客文章的编辑功能.1. 使用ueditor过程中会请求一个后台js文件 ...
- Python random() 函数
描述 random() 方法返回随机生成的一个实数,它在[0,1)范围内. 语法 以下是 random() 方法的语法: import random random.random() 注意:random ...
- 「SDOI2018」物理实验
题目大意: 这题不好描述,直接看原题吧…… 题解: 很无脑的题……就是卡精度+难写.代码能力还是太差了. 其实可以直接用long double肝过去.但我的代码似乎太丑了,以至于跑得奇慢无比. 代码: ...
- 【bzoj 4407】于神之怒加强版
Description 给下N,M,K.求 Input 输入有多组数据,输入数据的第一行两个正整数T,K,代表有T组数据,K的意义如上所示,下面第二行到第T+1行,每行为两个正整数N,M,其意 ...
- keepalived工作原理和配置说明
keepalived是什么 keepalived是集群管理中保证集群高可用的一个服务软件,其功能类似于heartbeat,用来防止单点故障. keepalived工作原理 keepalived是以VR ...
- 越来越火的"中台"是什么
很多企业都将促进业务与科技的深度融合作为发展战略,也都想学学阿里的中台战略,其实,除了中台战略之外,基于企业级业务架构设计来实现组件化开发也是企业数字化转型的优选路径,是弥合业务与技术之间“数字鸿沟” ...
- Nginx 配置 Https 免费证书访问
配置HTTPS 现在做博客或者做网站没有 https 已经不行了,就记录一下我在腾讯云配置 https 的过程吧,非常简单,1个小时就可以了. 还涉及到 http 访问自动转发到 https 访问路径 ...
- 死磕 java集合之LinkedBlockingQueue源码分析
问题 (1)LinkedBlockingQueue的实现方式? (2)LinkedBlockingQueue是有界的还是无界的队列? (3)LinkedBlockingQueue相比ArrayBloc ...
- Python爬虫入门教程 57-100 python爬虫高级技术之验证码篇3-滑动验证码识别技术
滑动验证码介绍 本篇博客涉及到的验证码为滑动验证码,不同于极验证,本验证码难度略低,需要的将滑块拖动到矩形区域右侧即可完成. 这类验证码不常见了,官方介绍地址为:https://promotion.a ...
- 百度病了,必应挂了,Yandex疯了。
前天一篇<搜索引擎百度已死>的文章火遍了互联网圈.文中作者指出如今的百度搜索首页一大半都是百度自家的产品,比如你搜索特普朗,你会发现第一页的结果分别是:百度百科.贴吧.百家号.百家号.百家 ...