NET Core微服务之路:弹性和瞬态故障处理库Polly的介绍
前言
瞬态故障:
过载故障:
Polly介绍
安装最新的Polly库
Polly故障策略(措施)
一个简单的异常
- try
- {
- var z = ;
- var r = / z;
- }
- catch (DivideByZeroException ex)
- {
- throw ex;
- }
很友好,也很直观。但假如这不是一个除以0的数学异常,而只是一个其他异常,并且需要我们调用端通过重试或者等待一段时间后才能正常调用的处理呢,比如一个异步的操作方法,我不能将上面的代码加上个for循环,或者调个线程阻塞一下吧,不管理论上为了目的和结果是可以这样写,我们重试10次,可以写成这样。
- for (int i = ; i < ; i++)
- {
- try
- {
- var z = ;
- var r = / z;
- }
- catch (DivideByZeroException ex)
- {
- throw ex;
- }
- }
Policy定义
故障定义
- // 特定异常
- Policy.Handle<DivideByZeroException>();
- // 条件异常
- Policy.Handle<ArgumentException>(ex => ex.HResult == );
- // 多重异常
- Policy.Handle<DivideByZeroException>().Or<ArgumentException>();
- // 聚合异常
- Policy.Handle<ArgumentException>().Or<ArgumentException>();
结果定义
- // 处理带条件的返回值
- Policy.HandleResult<HttpResponseMessage>(r => r.StatusCode == HttpStatusCode.NotFound);
- // 处理多个条件的返回值
- Policy.HandleResult<HttpResponseMessage>(r => r.StatusCode == HttpStatusCode.InternalServerError)
- .OrResult(r => r.StatusCode == HttpStatusCode.BadGateway);
- // 结果判断
- Policy.HandleResult<int>(ret => ret <= );
故障处理策略定义
- // 重试1次
- Policy.Handle<TimeoutException>().Retry();
- // 重试3次
- Policy.Handle<TimeoutException>().Retry();
- // 无限重试
- Policy.Handle<TimeoutException>().RetryForever();
- // 重试多次,每次重试都调用一个操作
- Policy.Handle<TimeoutException>().Retry(, (exception, retryCount) =>
- {
- // do something
- });
- // 重试固定时间间隔 (1)
- Policy.Handle<TimeoutException>().WaitAndRetry(, _ => TimeSpan.FromSeconds());
- // 重试指定时间时间 (2)
- Policy.Handle<TimeoutException>().WaitAndRetry(new[]
- {
- TimeSpan.FromSeconds(),
- TimeSpan.FromSeconds(),
- TimeSpan.FromSeconds()
- }, (exception, timeSpan, retryCount, context) =>
- {
- // do something
- });
回退定义
- // 返回一个值
- Policy<int>.Handle<TimeoutException>().Fallback();
- Policy<int>.Handle<TimeoutException>().Fallback(() => );
- // 或将返回值定义为一个方法
- Policy.Handle<TimeoutException>().Fallback(() => { });
断路保护定义
- // 在指定的连续异常数后断开,并在指定的持续时间内保持断开。
- Policy.Handle<TimeoutException>().CircuitBreaker(, TimeSpan.FromMinutes());
- // 在指定的连续异常数后断开,并在规定的时间内保持电路断开,且调用一个改变状态的操作。
- var circuitBreaker = Policy.Handle<TimeoutException>().CircuitBreaker(, TimeSpan.FromMinutes(),
- (exception, timespan) =>
- {
- // On Break
- },
- () =>
- {
- // On Reset
- });
- // 获取当前断路器的状态 (1)
- var circuitState = circuitBreaker.CircuitState;
- // 除了超时和策略执行失败的这种自动方式外,也可以手动控制它的状态:
- // 手动打开(且保持)一个断路器,例如手动隔离downstream服务
- circuitBreaker.Isolate();
- // 重置一个断路器回closed的状态,可再次接受actions的执行
- circuitBreaker.Reset();
策略定义(弹性策略)
- // 一个简单混合(弹性)策略:当重试2次后,自动回退100
- var fallback = Policy<int>.Handle<TimeoutException>().Fallback();
- var retry = Policy<int>.Handle<TimeoutException>().Retry();
- var policyWrap = Policy.Wrap(fallback, retry);
- policyWrap.Execute(() => { return ; });
- // 超时策略用于控制委托的运行时间,如果达到指定时间还没有运行,则触发超时异常。
- Policy.Timeout(TimeSpan.FromSeconds(), TimeoutStrategy.Pessimistic); ()
- // 无操作策略(NoOp),啥也不不干
- Policy.NoOp();
- // 舱壁隔离(Bulkhead Isolation)
- // 舱壁隔离是一种并发控制的行为,并发控制是一个比较常见的模式,Polly也提供了这方面的支持
- Policy.Bulkhead();
- // 超过了并发数的任务会抛BulkheadRejectedException,如果要放在队列中等待
- // 这种方式下,有12个并发任务,每个任务维持着一个并发队列,每个队列可以自持最大100个任务。
- Policy.Bulkhead(, );
重试操作
- public static void Retry()
- {
- var tick = ;
- const int maxRetry = ;
- var retry = Policy.Handle<Exception>().Retry(maxRetry);
- try
- {
- retry.Execute(() =>
- {
- Console.WriteLine($@"try {++tick}");
- if (tick >= )
- // 出现故障,开始重试Execute
- throw new Exception("throw the exception");
- });
- }
- catch (Exception ex)
- {
- Console.WriteLine(@"exception : " + ex.Message);
- }
- }
我们定义一个最大重试次数为6的常亮,和一个为Retry的Policy委托,通过委托执行retry.Execute()方法中,强制抛出一个异常,每抛出一次异常,将计数器+1(实际重试了7次),执行结果如下:
- try
- try
- try
- try
- try
- try
- try
- exception : throw the exception
回退操作
- public static void Fallback()
- {
- Policy.Handle<ArgumentException>().Fallback(() => { Console.WriteLine(@"error occured"); })
- .Execute(() =>
- {
- Console.WriteLine(@"try");
- // 出现故障,进行降级处理Fallback
- throw new ArgumentException(@"throw the exception");
- });
- }
以上代码解释:当委托方法中出现异常,在回退操作的控制台中输出一句话“error occured”,执行结果如下:
- try
- error occured
缓存操作
- public static void Cache()
- {
- const int ttl = ;
- var policy = Policy.Cache(new MemoryCacheProvider(new MemoryCache(new MemoryCacheOptions())), TimeSpan.FromSeconds(ttl));
- var context = new Context(operationKey: "cache_key");
- for (var i = ; i < ; i++)
- {
- var cache = policy.Execute(_ =>
- {
- Console.WriteLine(@"get value");
- return ;
- }, context);
- Console.WriteLine(cache);
- }
- }
Polly支持Cache的操作,你可以使用Memory、Redis等缓存提供器来支持Polly的缓存处理。代码中,我们使用Context来设置一个Key,通过委托执行3次,每次都通过这个缓存来获取值,执行结果如下:
- get value
断路操作
- public static void CircuitBreaker()
- {
- var tick = ;
- const int interval = ;
- const int maxRetry = ;
- var circuitBreaker = Policy.Handle<Exception>().CircuitBreaker(maxRetry, TimeSpan.FromSeconds(interval));
- while (true)
- {
- try
- {
- circuitBreaker.Execute(() =>
- {
- Console.WriteLine($@"try {++tick}");
- throw new Exception("throw the exception");
- });
- }
- catch (Exception ex)
- {
- Console.WriteLine(@"exception : " + ex.Message);
- // 当重试次数达到断路器指定的次数时,Polly会抛出The circuit is now open and is not allowing calls. 断路器已打开,不允许访问
- // 为了演示,故意将下面语句写上,可退出while循环
- // 实际环境中视情况,断开绝不等于退出,或许20-30秒后,服务维护后变得可用了
- if (ex.Message.Contains("The circuit is now open and is not allowing calls"))
- {
- break;
- }
- }
- Thread.Sleep();
- }
- }
这段代码稍微有点多,我们先看看执行结果:
- try
- exception : throw the exception
- try
- exception : throw the exception
- try
- exception : throw the exception
- try
- exception : throw the exception
- try
- exception : throw the exception
- try
- exception : throw the exception
- exception : The circuit is now open and is not allowing calls.
弹性操作
- public static void Timeout()
- {
- const int timeoutSecond = ;
- try
- {
- Policy.Wrap(
- Policy.Timeout(timeoutSecond, TimeoutStrategy.Pessimistic),
- Policy.Handle<TimeoutRejectedException>().Fallback(() => { })
- ).Execute(() =>
- {
- Console.WriteLine(@"try");
- Thread.Sleep();
- });
- }
- catch (Exception ex)
- {
- // 当超时时间到,会抛出The delegate executed through TimeoutPolicy did not complete within the timeout.
- // 委托执行未在指定时间内完成
- Console.WriteLine($@"exception : {ex.GetType()} : {ex.Message}");
- }
- }
以上策略很好理解,组合一个超时和回退的策略组合,当超时已到,执行回退操作,执行结果如下:
- try
- exception : Polly.Timeout.TimeoutRejectedException : The delegate executed through TimeoutPolicy did not complete within the timeout.
.png)
总结
感谢阅读!
NET Core微服务之路:弹性和瞬态故障处理库Polly的介绍的更多相关文章
- 已被.NET基金会认可的弹性和瞬态故障处理库Polly介绍
前言 本节我们来介绍一款强大的库Polly,Polly是一种.NET弹性和瞬态故障处理库,允许我们以非常顺畅和线程安全的方式来执诸如行重试,断路,超时,故障恢复等策略. Polly针对对.NET 4. ...
- 弹性和瞬态故障处理库Polly
介绍 本节我们来介绍一款强大的库Polly,Polly是一种.NET弹性和瞬态故障处理库,允许我们以非常顺畅和线程安全的方式来执诸如行重试,断路,超时,故障恢复等策略. Polly针对对.NET 4. ...
- .NET Core微服务之路:文章系列和内容索引汇总 (v0.52)
微服务架构,对于从事JAVA架构的童鞋来说,早已不是什么新鲜的事儿,他们有鼎鼎大名的Spring Cloud这样的全家桶框架支撑,包含微服务核心组件如 1. Eureka:实现服务注册与发现. 2. ...
- NET Core微服务之路:实战SkyWalking+Exceptionless体验生产环境下的追踪系统
前言 当一个APM或一个日志中心实际部署在生产环境中时,是有点力不从心的. 比如如下场景分析的问题: 从APM上说,知道某个节点出现异常,或延迟过过高,却不能及时知道日志反馈情况,总不可能去相应的节点 ...
- NET Core微服务之路:实战SkyWalking+Exceptionless体验生产下追踪系统
原文:NET Core微服务之路:实战SkyWalking+Exceptionless体验生产下追踪系统 前言 当一个APM或一个日志中心实际部署在生产环境中时,是有点力不从心的. 比如如下场景分析的 ...
- .NET Core微服务之路:不断更新中的目录 (v0.43)
原文:.NET Core微服务之路:不断更新中的目录 (v0.43) 微服务架构,对于从事JAVA架构的童鞋来说,早已不是什么新鲜的事儿,他们有鼎鼎大名的Spring Cloud这样的全家桶框架支撑, ...
- NET Core微服务之路:自己动手实现Rpc服务框架,基于DotEasy.Rpc服务框架的介绍和集成
本篇内容属于非实用性(拿来即用)介绍,如对框架设计没兴趣的朋友,请略过. 快一个月没有写博文了,最近忙着两件事; 一:阅读刘墉先生的<说话的魅力>,以一种微妙的,你我大家都会经常遇见 ...
- NET Core微服务之路:简单谈谈对ELK,Splunk,Exceptionless统一日志收集中心的心得体会
前言 日志,一直以来都是开发人员和运维人员最关心的问题.开发人员可通过日志记录来协助问题定位,运维人员可通过日志发现系统隐患,故障等定位问题.如果你的系统中没有日志,就像一个断了线的风筝,你永远不知道 ...
- .NET Core微服务之路:让我们对上一个Demo通讯进行修改,完成RPC通讯
最近一段时间有些事情耽搁了更新,抱歉各位了. 上一篇我们简单的介绍了DotNetty通信框架,并简单的介绍了基于DotNetty实现了回路(Echo)通信过程. 我们来回忆一下上一个项目的整个流程: ...
随机推荐
- PhpSpreadsheet处理表格
介绍:PhpSpreadsheet是PHPExcel的下一个版本.它打破了兼容性,大大提高了代码库质量(命名空间,PSR合规性,最新PHP语言功能的使用等).由于所有努力都转移到了PhpSpreads ...
- 实践中 XunSearch(讯搜)的使用教程步骤
XunSearch(讯搜)的使用教程步骤 一.安装编译工具 yum install make gcc g++ gcc-c++ libtool autoconf automake imake mysql ...
- roadhog如何支持除development和production外的其他环境变量配置
roadhog的build和start脚本分别对应了env/development和production,但实践中存在第三种开发环境(可能是预发或集成测试),配置和前两种也都不一样,但现在似乎没办法支 ...
- POM文件详解(1)
POM文件详解 <project xmlns=http://maven.apache.org/POM/4.0.0 xmlns:xsi="http://www.w3.org/2001/X ...
- js操作bom和dom
Bom 概念 BOM : Browser Object Model 浏览器对象模型,描述与浏览器进行交互的方法和接 口, ECMAscript是javascript的核心,但如果要在web中使用jav ...
- webapi使用swagger出现“Cannot read property 'parameters' of null”
前端时间在webapi项目使用swagger来提供接口文档及测试工具,按网上方法(http://wmpratt.com/swagger-and-asp-net-web-api-part-1)配置好之后 ...
- Leetcode35 Search Insert Position 解题思路(python)
本人编程小白,如果有写的不对.或者能更完善的地方请个位批评指正! 这个是leetcode的第35题,这道题的tag是数组,python里面叫list,需要用到二分搜索法 35. Search Inse ...
- html-有趣的标签-会移动的文字
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" ...
- gogs 安装
docker 安装gogs 准备工作 安装一个mysql数据库,创建一个数据库 gogs,字符集为utf-8 查找gogs 镜像 docker search gogs 拉取镜像到本地 docker p ...
- Unable to launch the IIS Express Web server
尝试运行程序,出现此异常提示Unable to launch the IIS Express Web server. 解决问题,是把网址修改为另一个试试: 把http://localhost:1114 ...