【编辑推荐】.NETCore微服务之路:弹性和瞬态故障处理库Polly的
来源:net 网络用户发布,如有版权联系网管删除 2019-02-27
public static void Retry(){ var tick = 0; const int maxRetry = 6; var retry = Policy.Handle().Retry(maxRetry); try { retry.Execute(() => { Console.WriteLine($@"try {++tick}"); if (tick >= 1) // 出现故障,开始重试Execute throw new Exception("throw the exception"); }); } catch (Exception ex) { Console.WriteLine(@"exception : " + ex.Message); }}
我们定义一个最大重试次数为6的常亮,和一个为Retry的Policy委托,通过委托执行retry.Execute()方法中,强制抛出一个异常,每抛出一次异常,将计数器+1(实际重试了7次),执行结果如下:
try 1try 2try 3try 4try 5try 6try 7exception : throw the exception
回退操作
public static void Fallback(){ Policy.Handle().Fallback(() => { Console.WriteLine(@"error occured"); }) .Execute(() => { Console.WriteLine(@"try"); // 出现故障,进行降级处理Fallback throw new ArgumentException(@"throw the exception"); });}
以上代码解释:当委托方法中出现异常,在回退操作的控制台中输出一句话“error occured”,执行结果如下:
tryerror occured
缓存操作
public static void Cache(){ const int ttl = 60; var policy = Policy.Cache(new MemoryCacheProvider(new MemoryCache(new MemoryCacheOptions())), TimeSpan.FromSeconds(ttl)); var context = new Context(operationKey: "cache_key"); for (var i = 0; i < 3; i++) { var cache = policy.Execute(_ => { Console.WriteLine(@"get value"); return 3; }, context); Console.WriteLine(cache); }}
Polly支持Cache的操作,你可以使用Memory、Redis等缓存提供器来支持Polly的缓存处理。代码中,我们使用Context来设置一个Key,通过委托执行3次,每次都通过这个缓存来获取值,执行结果如下:
get value333
断路操作
public static void CircuitBreaker(){ var tick = 0; const int interval = 10; const int maxRetry = 6; var circuitBreaker = Policy.Handle().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(300); }}
这段代码稍微有点多,我们先看看执行结果:
try 1exception : throw the exceptiontry 2exception : throw the exceptiontry 3exception : throw the exceptiontry 4exception : throw the exceptiontry 5exception : throw the exceptiontry 6exception : throw the exceptionexception : The circuit is now open and is not allowing calls.
从执行结果中我们可以看到,一共尝试重试了6次,超过6次后,直接返回The circuit is now open and is not allowing calls(断路器已打开,不允许调用)。
弹性操作
我们用一个超时来处理策略组合的弹性操作。
public static void Timeout(){ const int timeoutSecond = 3; try { Policy.Wrap( Policy.Timeout(timeoutSecond, TimeoutStrategy.Pessimistic), Policy.Handle().Fallback(() => { }) ).Execute(() => { Console.WriteLine(@"try"); Thread.Sleep(5000); }); } catch (Exception ex) { // 当超时时间到,会抛出The delegate executed through TimeoutPolicy did not complete within the timeout. // 委托执行未在指定时间内完成 Console.WriteLine($@"exception : {ex.GetType()} : {ex.Message}"); }}
以上策略很好理解,组合一个超时和回退的策略组合,当超时已到,执行回退操作,执行结果如下:
tryexception : Polly.Timeout.TimeoutRejectedException : The delegate executed through TimeoutPolicy did not complete within the timeout.
策略组合是Polly中强大的弹性操作核心,我们可以结合实际业务场景,来组合多个策略以满足我们对故障保护的需求,以下是Polly中Warp的方法源码:
.png?ext.jpg)
总结
本节只是简单的介绍了一下Polly这个弹性框架库的使用范围,我们可以通过它的故障定义和委托来实现熔断,降级,隔离,重试等操作,实现方式也非常简单(.Net的语法糖确实很甜),更强大的是她的弹性策略,结合到我们实际的业务中,可以保护(或处理)很多实际业务场景。比如一个支付失败的操作,可以尝试指定次数后回滚之前的支付操作,保护支付合规性。再或者,服务节点中某个接口存在异常,立马阻断与调用端的连接,并隔离这个异常的接口,等等业务场景。并且,不仅在Ocelot中也集成了这强大的弹性库,其他非常多的.Net开源框架也默认集成了Polly。
查看评论 回复