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)通信过程. 我们来回忆一下上一个项目的整个流程: ...
随机推荐
- DataStructs.h
#ifndef _DATASTRUCS_H__ #define _DATASTRUCS_H__ #include <systemc.h> #include "GlobalPara ...
- docker之tomcat简单部署
将apache-tomcat-8.0.36.tar.gz及jdk-7u79-linux-x64.gz拷贝到创建的tomcat8目录下 在tomcat8目录下创建Dockerfile文件 在Docker ...
- python3 django1.11 安装xadmin 的方法,亲测可用
首先需要Pip安装如下的包ip install django-crispy-forms pip install django-import-export pip install django-reve ...
- Particle Filters
|—粒子滤波原理 |—基础代码的建立—|—前进 | |—转弯 | |—噪音(误差 ...
- pyspider爬取tourism management 所有文章的标题 作者 摘要 关键词等等所有你想要的信息
#!/usr/bin/env python # -*- encoding: utf-8 -*- # vim: set et sw=4 ts=4 sts=4 ff=unix fenc=utf8: # C ...
- Unicode vs. UTF-8 etc.
目测是个老问题了.随便一搜,网上各种总结过.这里不辞啰嗦,尽量简洁的备忘一下. 几个链接,有道云笔记链接,都是知乎上几个问题的摘录:阮一峰的日志,1-5 还是值得参考,但是之后的部分则混淆了 Wind ...
- <笔记>三码合一
讲求三码合一,何为三码合一?(这里我用UTF8讲例子) 就是页面编码,文档编码,数据库编码要统一一种格式,切记不可有的是GBK,有的是UFT8 页面编码:也就是用header 函数申明:header( ...
- STM32的SWD调试进不了main函数
玩了那么久STM32,还没有用SWD调试过程序(一直都是用printf调试程序),觉得有些落后了,于是开始搞起了SWD调试. 很快通过查阅资料,知道了keil里面的配置和ST-Link与STM32的连 ...
- submit插件安装的问题与集成了插件的submit
写在最前面,方法有二种.一种是在线安装,这种办法我尝试过,受网速和软件卡顿的问题,进行不顺利.第二种就是我下面介绍的这种,手动安装. 最精华的在后面,可以直接跳转到最后.我找了很久的,最新版的汉化,而 ...
- 使用 VSTS 进行 CI 的过程中,无法识别 .NET Core 2.x 的情况处理
大概是由于 .NET Core 2.1 还没有正式发布,使用 VSTS 进行持续集成(CI)的过程中,自动 Build 的环节无法识别 .NET Core 2.1 的框架,查看日志会提示如下错误: V ...