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)通信过程. 我们来回忆一下上一个项目的整个流程: ...
随机推荐
- lsf运行lsload命令显示“lsload: Host does not have a software license”
因为这个问题也是花费好长时间了,对一个小白的我来说真的挺激动的.下面说一下我的解决思路吧.不过造成这个问题也有很多种原因,需要对症下药. 我入手解决是从这个网站上看到同样的问题,然后通过一个个排除最后 ...
- TCP的三次握手 与 四次挥手
TCP的连接建立是一个三次握手过程,目的是为了通信双方确认开始序号,以便后续通信的有序进行 主要步骤: 服务器一定处于Listen状态,否则客户端发过来的连接会被拒绝.注:服务器和客户端的角色是相对的 ...
- Python之路系列笔记
备注:本套笔记内容来源于互联网,只做学习使用,如有侵权请联系本笔记作者. 资料内容 Python之路(一)——Python 初识 Python之路(二)——基础语法 Python之路(三)——函数 P ...
- 用chrome模拟微信浏览器访问页面
有的网页通过限制 user agent 来达到禁止在微信浏览器以外的地方访问,我们通过chrome修改user agent即可破解. CHROME浏览器,进入开发者模式 切换到手机浏览模板 打开 N ...
- Windows 注册表 16进制时间转换( Convert Reg_binary Time to a Datetime )
背景: Windows注册表中,存在大量16进制的时间,以 reg_binary存储在注册表中. 例如: 0D 6C A4 4B 37 C5 CE 01 这种值日常报表中需要转换为适合人阅读的格式,实 ...
- python迭代器与生成器详解
迭代器与生成器 迭代器(iterator)与生成器(generator)是 Python 中比较常用又很容易混淆的两个概念,今天就把它们梳理一遍,并举一些常用的例子. for 语句与可迭代对象(ite ...
- Normalize.css & Reset
Normalize.css: try to keep the style consistent in every browser. Reset: clear style in every browse ...
- shell脚本新建文件夹或用到目录时多出M或者?之类的
新建问价加多出? 删除多显示M 建立软连接多\n等 可能是文件兼容问题, 1.首先用vi命令打开文件[root@localhost test]# vi test.sh 2.在vi命令模式中使用 ...
- VS code的疑惑之处
作为一个新手,我充满疑惑 eg:下载了git但无法使用匹配 然后在各位博主的详细解释下知道 VS code更新后的git.path被格式化了: so需要进行路径覆盖. 在这之后我的终端依旧出现问题 ...
- Java核心技术卷一基础知识-第5章-继承-读书笔记
第5章 继承 本章内容: * 类.超类和子类 * Object:所有类的超类 * 泛型数组列表 * 对象包装器和自动装箱 * 参数数量可变的方法 * 枚举类 * 反射 * 继承设计的技巧 利用继承,人 ...