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)通信过程. 我们来回忆一下上一个项目的整个流程: ...
随机推荐
- vue中引入vux
1.安装相关依赖 cnpm install vux --save cnpm install vux-loader --save-dev cnpm install less less-loader -- ...
- 为创世纪图书馆(Library Genesis)作镜像
简介 Library Genesis的Wikipedia条目中的介绍是: Library Genesis or LibGen is a search engine for articles and b ...
- Django学习(一)连接mysql
python3.6 Django2.0 几个改动的点: 1)setting: 2)__init__.py import pymysql 然后再重启server python manage.py run ...
- react整理一二(初入React世界)
react重要思想:组件化(按钮组件.对话框组件.日期组件等等).JSX语法 react把代码和正式渲染目标隔离开来,除了可以在浏览器渲染到DOM来开发网页,还能用于开发原生移动运用 1.专注视图层: ...
- weexpack打包weex项目运行/打包记录
构建weex项目 安装weex-toolkit cnpm install -g weex-toolkit 初始化一个项目只需新建文件夹并在目录下执行 weex init 即可 安装依赖:cnpm in ...
- Javascript高级编程学习笔记(54)—— DOM2和DOM3(6)范围选择
范围 为了让开发人员更加方便地控制页面“DOM2级遍历和范围”模块定义了“范围”接口 通过该接口开发人员可以选择文档中的一个区域,而不必考虑元素的界限 在常规操作不能有效地修改文档时,使用范围往往可以 ...
- dubbo集群容错解决方案
dubbo主要核心部件 Remoting:网络通信框架,实现了sync-over-async和request-response消息机制. RPC:一个远程过程调用的抽象,支持负载均衡.容灾和集群功能. ...
- Robot Framework - 1 - 测试用例与测试库
01- 关于测试库(Test libraries) Test libraries provide the actual testing capabilities to Robot Framework ...
- Python - 使用Pylint检查分析代码
1-简介 Home Page : https://www.pylint.org/ 检查语法错误,是否遵守编码风格标准.潜在的问题等: 支持自定义配置:例如显示或隐藏特定的警告,并且可以通过编写插件来添 ...
- android自动化必备之界面元素
包名&类名 packageName(包名) 应用的身份标识,系统通过包名识别不同的应用,如两个相同包名的应用在安装时候会覆盖 activityName(类名) Activity:android ...