容错处理库Polly使用文档
Design For Failure
1. 一个依赖服务的故障不会严重破坏用户的体验。
2. 系统能自动或半自动处理故障,具备自我恢复能力。
以下是一些经验的服务容错模式
- 超时与重试(Timeout and Retry)
- 限流(Rate Limiting)
- 熔断器(Circuit Breaker)
- 舱壁隔离(Bulkhead Isolation)
- 回退(Fallback)
如果想详细了解这几种模式可以参考美团技术团队的总结:服务容错模式。我们今天要讲的是,thanks to the community 多谢社区, Polly已经为我们实现了以上全部的功能。Polly是一个C#实现的弹性瞬时错误处理库(resilience and transient-fault-handling library一直觉得这个英文翻译不是很好) 。在Polly中,对这些服务容错模式分为两类:
- 错误处理fault handling :重试、熔断、回退
- 弹性应变resilience:超时、舱壁、缓存
可以说错误处理是当错误已经发生时,防止由于该错误对整个系统造成更坏的影响而设置。而弹性应变,则在是错误发生前,针对有可能发生错误的地方进行预先处理,从而达到保护整个系统的目地。
Polly 错误处理使用三步曲
- 定义条件: 定义你要处理的 错误异常/返回结果
- 定义处理方式 : 重试,熔断,回退
- 执行
var policy = Policy
.Handle<SomeExceptionType>() // 定义条件
.Retry(); // 定义处理方式 // 执行
policy.Execute(() => DoSomething());
定义条件
我们可以针对两种情况来定义条件:错误异常和返回结果。
// 单个异常类型
Policy
.Handle<HttpRequestException>() // 限定条件的单个异常
Policy
.Handle<SqlException>(ex => ex.Number == ) // 多个异常类型
Policy
.Handle<HttpRequestException>()
.Or<OperationCanceledException>() // 限定条件的多个异常
Policy
.Handle<SqlException>(ex => ex.Number == )
.Or<ArgumentException>(ex => ex.ParamName == "example") // Inner Exception 异常里面的异常类型
Policy
.HandleInner<HttpRequestException>()
.OrInner<OperationCanceledException>(ex => ex.CancellationToken != myToken)
以及用返回结果来限定
// 返回结果加限定条件
Policy
.HandleResult<HttpResponseMessage>(r => r.StatusCode == HttpStatusCode.NotFound) // 处理多个返回结果
Policy
.HandleResult<HttpResponseMessage>(r => r.StatusCode == HttpStatusCode.InternalServerError)
.OrResult<HttpResponseMessage>(r => r.StatusCode == HttpStatusCode.BadGateway) // 处理元类型结果 (用.Equals)
Policy
.HandleResult<HttpStatusCode>(HttpStatusCode.InternalServerError)
.OrResult<HttpStatusCode>(HttpStatusCode.BadGateway) // 在一个policy里面同时处理异常和返回结果。
HttpStatusCode[] httpStatusCodesWorthRetrying = {
HttpStatusCode.RequestTimeout, //
HttpStatusCode.InternalServerError, //
HttpStatusCode.BadGateway, //
HttpStatusCode.ServiceUnavailable, //
HttpStatusCode.GatewayTimeout //
};
HttpResponseMessage result = Policy
.Handle<HttpRequestException>()
.OrResult<HttpResponseMessage>(r => httpStatusCodesWorthRetrying.Contains(r.StatusCode))
.RetryAsync(...)
.ExecuteAsync( /* some Func<Task<HttpResponseMessage>> */ )
定义处理方式
在这里使用的处理方式就是我们最开始说的服务容错模式,我们将介绍以下三种:重试、熔断、回退。
重试
重试很好理解,当发生某种错误或者返回某种结果的时候进行重试。Polly里面提供了以下几种重试机制
- 按次数重试
- 不断重试(直到成功)
- 等待之后按次数重试
- 等待之后不断重试(直到成功)
按次数重试
// 重试1次
Policy
.Handle<SomeExceptionType>()
.Retry() // 重试3(N)次
Policy
.Handle<SomeExceptionType>()
.Retry() // 重试多次,加上重试时的action参数
Policy
.Handle<SomeExceptionType>()
.Retry(, (exception, retryCount) =>
{
// 干点什么,比如记个日志之类的
});
不断重试
// 不断重试,直到成功
Policy
.Handle<SomeExceptionType>()
.RetryForever() // 不断重试,带action参数在每次重试的时候执行
Policy
.Handle<SomeExceptionType>()
.RetryForever(exception =>
{
// do something
});
等待之后重试
// 重试3次,分别等待1、2、3秒。
Policy
.Handle<SomeExceptionType>()
.WaitAndRetry(new[]
{
TimeSpan.FromSeconds(),
TimeSpan.FromSeconds(),
TimeSpan.FromSeconds()
});
当然也可以在每次重试的时候添加一些处理,这里我们可以从上下文中获取一些数据,这些数据在policy启动执行的时候可以传进来。
Policy
.Handle<SomeExceptionType>()
.WaitAndRetry(new[]
{
TimeSpan.FromSeconds(),
TimeSpan.FromSeconds(),
TimeSpan.FromSeconds()
}, (exception, timeSpan, context) => {
// do something
});
熔断
熔断也可以被作为当遇到某种错误场景下的一个操作。以下代码展示了当发生2次SomeExceptionType的异常的时候则会熔断1分钟,该操作后续如果继续尝试执行则会直接返回错误 。
Policy
.Handle<SomeExceptionType>()
.CircuitBreaker(, TimeSpan.FromMinutes());
可以在熔断和恢复的时候定义委托来做一些额外的处理。onBreak会在被熔断时执行,而onReset则会在恢复时执行。
熔断器状态
我们的CircuitBreakPolicy的State定义了当前熔断器的状态,我们也可能调用它的Is
Action<Exception, TimeSpan> onBreak = (exception, timespan) => { ... };
Action onReset = () => { ... };
CircuitBreakerPolicy breaker = Policy
.Handle<SomeExceptionType>()
.CircuitBreaker(, TimeSpan.FromMinutes(), onBreak, onReset);
Isolate和Reset方法来手动熔断和恢复 。
CircuitState state = breaker.CircuitState;
- Closed 关闭状态,允许执行
- Open 自动打开,执行会被阻断
- Isolate 手动打开,执行会被阻断
- HalfOpen 从自动打开状态恢复中,在熔断时间到了之后从Open状态切换到Closed
// 手动打开熔断器,阻止执行
breaker.Isolate();
// 恢复操作,启动执行
breaker.Reset();
回退(Fallback)
// 如果执行失败则返回UserAvatar.Blank
Policy
.Handle<Whatever>()
.Fallback<UserAvatar>(UserAvatar.Blank) // 发起另外一个请求去获取值
Policy
.Handle<Whatever>()
.Fallback<UserAvatar>(() => UserAvatar.GetRandomAvatar()) // where: public UserAvatar GetRandomAvatar() { ... } // 返回一个指定的值,添加额外的处理操作。onFallback
Policy
.Handle<Whatever>()
.Fallback<UserAvatar>(UserAvatar.Blank, onFallback: (exception, context) =>
{
// do something
});
执行polly policy
为我声明了一个Policy,并定义了它的异常条件和处理方式,那么接下来就是执行它。执行是把我们具体要运行的代码放到Policy里面。
// 执行一个Action
var policy = Policy
.Handle<SomeExceptionType>()
.Retry(); policy.Execute(() => DoSomething());
// 看我们在retry重试时被调用的一个委托,它可以从context中拿到我们在execute的时候传进来的参数 。
var policy = Policy
.Handle<SomeExceptionType>()
.Retry(, (exception, retryCount, context) =>
{
var methodThatRaisedException = context["methodName"];
Log(exception, methodThatRaisedException);
}); policy.Execute(
() => DoSomething(),
new Dictionary<string, object>() {{ "methodName", "some method" }}
);
Policy
.Handle<SqlException>(ex => ex.Number == )
.Or<ArgumentException>(ex => ex.ParamName == "example")
.Retry()
.Execute(() => DoSomething());
protected async Task<T> ExecuteDb<T>(IServiceExecuteContext context, Func<Task<T>> action, string actionName = null, bool retryForever = false)
{
RetryPolicy policy = null;
var policyBuilder = Policy
.Handle<SqlException>(ex => ex.Number == ); // Handle Deadlock Retry if (retryForever)
{
policy = policyBuilder.WaitAndRetryForeverAsync((time, retryCtx) => TimeSpan.FromMilliseconds(time * ), (ex, time, retryCtx) =>
{
if (time.TotalSeconds > )
{
Log.Error($"{context.GetCurrentLogMessagePrefix()} {actionName}发生死锁正在重试(等待{time.TotalSeconds}秒)(已重试超过30次!!!!请引起重视!!!!)");
}
else
{
Log.Warn($"{context.GetCurrentLogMessagePrefix()} {actionName}发生死锁正在重试(等待{time.TotalSeconds}秒)");
}
});
}
else
{
policy = policyBuilder.WaitAndRetryAsync(new[]
{
TimeSpan.Zero,
TimeSpan.FromMilliseconds( * ),
TimeSpan.FromMilliseconds( * )
}, (ex, time, retryCtx) =>
{
Log.Warn($"{context.GetCurrentLogMessagePrefix()} {actionName}发生死锁正在重试(等待{time.TotalSeconds}秒)");
});
} return await policy.ExecuteAsync(async () => await action());
}
摘自 :https://www.cnblogs.com/jesse2013/p/polly-docs.html
容错处理库Polly使用文档的更多相关文章
- ASP VNext 开源服务容错处理库Polly使用文档
在进入SOA之后,我们的代码从本地方法调用变成了跨机器的通信.任何一个新技术的引入都会为我们解决特定的问题,都会带来一些新的问题.比如网络故障.依赖服务崩溃.超时.服务器内存与CPU等其它问题.正是因 ...
- 服务容错处理库Polly使用
服务容错处理库Polly使用 在进入SOA之后,我们的代码从本地方法调用变成了跨机器的通信.任何一个新技术的引入都会为我们解决特定的问题,都会带来一些新的问题.比如网络故障.依赖服务崩溃.超时.服务器 ...
- 如何实现SP文档库类似百度文档库的效果 (副标题:如何在SP2013文档库的SWF文件用FlexPager显示)
1. 编辑文档库列表显示页面,如下图: 2. 添加内容编辑器,如下图: 3. 添加如下在[内容编辑器中]-[编辑源],添加如下JS代码,如下图: 代码如下: <scrip type=&quo ...
- 转:在 C# 中使用 P/Invoke 调用 Mupdf 函数库显示 PDF 文档
在 C# 中使用 P/Invoke 调用 Mupdf 函数库显示 PDF 文档 一直以来,我都想为 PDF 补丁丁添加一个 PDF 渲染引擎.可是,目前并没有可以在 .NET 框架上运行的免费 PDF ...
- 使用Python爬虫库BeautifulSoup遍历文档树并对标签进行操作详解(新手必学)
为大家介绍下Python爬虫库BeautifulSoup遍历文档树并对标签进行操作的详细方法与函数下面就是使用Python爬虫库BeautifulSoup对文档树进行遍历并对标签进行操作的实例,都是最 ...
- https://github.com/coolnameismy/BabyBluetooth github上的一个ios 蓝牙4.0的库并带文档和教程
The easiest way to use Bluetooth (BLE )in ios,even bady can use. 简单易用的蓝牙库,基于CoreBluetooth的封装,并兼容ios和 ...
- SharePoint 2007 文档库中的文档添加评论功能
背景:接到一个项目,要求文档管理,当然文档库就可以了,但是要求文档需要大家去读,读完以后还可以发表评论,这Moss貌似就有点困难了.和同事一起合计,想来想去也没有太好的办法,后来想到传统开发,两个表的 ...
- 如何制作dll库的API文档,自动生成微软风格的chm文件 Sandcastle Help File Builder 使用方法
当你开发了一个库的时候,就需要给库开发一个api文档,微软提供了一个C#库的自动生成工具.我在使用的过程中记录了相关的信息,以供大家学习和查阅,如有不正之处,欢迎指出. 首先先下载一个软件,下载地址在 ...
- Jsoup库 解析DOM文档
DOM文档包括 HTML, XML等等 下载: http://jsoup.org/download Jsoup 获取数据的方式 //html 文本, url, 本地html String html = ...
随机推荐
- [置顶] 在Visual Studio 2008上调试C语言程序
C语言的地位和重要性就不用说了,但,很多人学习C语言,还在使用Visual C++ 6.0,甚至还有人使用Turbo C,很无语,只说一句吧:“OUT了". 让我们体验一下华丽的Visual ...
- python解析命令行参数
常常需要解析命令行参数,经常忘记,好烦,总结下来吧. 1.Python 中也可以所用 sys 的 sys.argv 来获取命令行参数: sys.argv 是命令行参数列表 参数个数:len(sys.a ...
- VB数组的清除
在一个程序中,同一数组只能用Dim语句定义一次.但有时可能需要清除数组的内容或对数组重新定义,这可以用:Erase语句来实现. 格式:Erase(数组名)[,(数组名)] 功能:用于重新初始化静态数组 ...
- SourceTree安装教程
一.安装Git 链接: http://pan.baidu.com/s/1mh7rICK 密码: 48dj 二.安装SourceTree 链接: http://pan.baidu.com/s/1skWk ...
- 【Zookeeper】源码分析之持久化(二)之FileSnap
一.前言 前篇博文已经分析了FileTxnLog的源码,现在接着分析持久化中的FileSnap,其主要提供了快照相应的接口. 二.SnapShot源码分析 SnapShot是FileTxnLog的父类 ...
- Python学习笔记九:正则表达式
一:正则表达式的符号与方法 常用符号: .:匹配任何一个字符,换行符除外(所以,多行字符串中的匹配要特殊处理,见下面实例) *:匹配前一个字符0次或多次 +:匹配前一个字符1次或多次 ?:匹配前一个字 ...
- SpringBoot集成自定义HandlerMethodArgumentResolver
传统SpringMVC集成自定义HandlerMethodArgumentResolver的方式为:http://www.cnblogs.com/yangzhilong/p/6282218.html ...
- SElinux测试及排错
一.修改SElinux的状态 #sestatus --查看状态 #setenforce --临时修改 #setenforce #getenforce #vim /etc/selinux/config ...
- 三种分布式对象主流技术——COM、Java和COBRA
既上一遍,看到还有一遍将关于 对象的, 分布式对象, 故摘抄入下: 目前国际上,分布式对象技术有三大流派——COBRA.COM/DCOM和Java.CORBA技术是最早出现的,1991年OMG颁布了C ...
- web-app_2_5.xsd内容
<?xml version="1.0" encoding="UTF-8"?> <xsd:schema xmlns="http://w ...