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)通信过程. 我们来回忆一下上一个项目的整个流程: ...
随机推荐
- 数据结构C语言版-队列
#include <stdlib.h> #include <stdio.h> #include <iostream> using namespace std; ty ...
- 卸载HDP大数据平台
使用以下说明卸载HDP: 停止所有已安装的HDP服务.请参阅HDP参考指南中的停止HDP服务. 如果安装了Knox,请在所有群集节点上运行以下命令: 对于RHEL / CentOS / Oracle ...
- 理解特性attribute 和 属性property的区别 及相关DOM操作总结
查一下英语单词解释,两个都可以表示属性.但attribute倾向于解释为特质,而property倾向于解释私有的.这个property的私有解释可以更方便我们下面的理解. 第一部分:区别点 第一点: ...
- python 队列结合线程的使用
from queue import Queue from threading import Thread import time q = Queue() def add_to_queue(): for ...
- Maven和Gradle的区别
转自:http://www.infoq.com/cn/news/2011/04/xxb-maven-6-gradle Maven面临的挑战 软件行业新旧交替的速度之快往往令人咂舌,不用多少时间,你就会 ...
- js every some 遍历函数理解
1.every let arr = [0, 1, 2, 3, 4, 5]; let result = arr.every((item, index) => { return item >= ...
- day17_雷神_数据库 小全
# 数据库 1.mysql 介绍 一 数据库管理软件的由来 程序的所有组件不可能只在一个机子上,性能问题和单点故障, 程序分散了,还需要解决数据共享问题, 基于网络访问这台共享的机器,用socket. ...
- JAVA主流框架---SSM整合
1.通过监听器的形式引入spring 2.SpringMVC容器和Spring容器间的关系 3.汇通的主旨 让大家熟练掌握SSM调用过程.并且将后台调用彻底掌握. 4.传统项目的搭建的弊端 1.传 ...
- Visual Studio 开发(一):安装配置Visual Studio Code
一.为何使用Visual Studio Code 在学习音视频开发的时候,使用到了C和C++,在回顾复习C和C++的知识的时候,需要编写一些代码来加强理解. 虽然,有在线的语言编辑工具https:// ...
- python写的压缩软件
import tkinterimport tkinter.filedialogimport osimport zipfileimport tkinter.messagebox #创建住窗口root = ...