目录
前言
对于运行中的系统,可以说百分百的小伙伴会经常遇见以下问题:
-
网络不通,突然又好了;
-
服务器宕机了;
-
调用服务接口超时了;
-
调用接口报错啦;
-
通讯信息发送失败需要重发;
以上只是列举了一些常遇到的问题,对于一些小项目可能简单的处理一下就OK了(比如重启或是重新发布),而对于微服务架构的项目,可能因为一个服务挂掉、或是一台服务器宕机、又或是网络出现波动等情况,都可能会导致业务流程失败,甚至会导致整个系统崩掉。所以对于系统瞬时故障需及时做出应对策略,对于可能会发生的故障需提前预防(弹性应变);Polly这个库针对以上等情况进行封装,通过策略的方式,灵活处理相关场景。
正文
1. 简介
Polly是一种.NET弹性和瞬态故障处理库,可以通过不同策略处理和应对故障场景,主要分为两大类:被动策略和主动策略,各自包含如下功能:
1.1 被动策略
主要针对故障的处理,避免如下:
-
重试(Retry):在实际应用场景中往往有些失败只是瞬时的,经过短暂的延时就可恢复,这种情况就可以采用重试策略;
-
熔断(Circuit Breaker):比如在调用接口发生异常时,当多次都返回异常,建议先熔断一段时间,即不再处理业务接口,直接报错;待熔断时间过了之后可以重新处理请求,即快速响应失败比让用户一直等待要合理;
-
回退(Fallback):如果失败之后怎么处理?即在发生故障的时候找一个替代逻辑进行处理, 比如返回指定的结果或是进行下一步操作;
1.2 主动策略
主要是进行弹性扩展,而不是针对故障处理,关键点是改变原有业务逻辑的执行行为,比如原业务逻辑超时了,就会执行指定的超时处理行为;
-
超时(Timeout ):确保调用者永远不需要等待超过配置的超时时间,不然就会触发超时异常;主要就是为了提升用户体验;
-
舱壁隔离(Bulkhead Isolation):即一个服务的故障不应该影响到整个系统(隔离);通过控制资源消耗,避免一个故障导致级联服务也故障,最终影响整个系统;目的就是进行并发控制(限流),避免故障带来的大范围影响。
-
缓存(Cache):将数据存入缓存中,后续的响应可以从缓存中获取; 目的就是为了提升性能;
-
策略包装( PolicyWrap):策略可以组合进行使用;目的就是为了方便各种策略组合进行业务故障处理;
大概理解Polly功能之后,接下来就通过Demo的形式进一步了解各策略的使用;
2. 功能Demo演示
Polly使用步骤很简单,两个步骤完事:
-
定义策略;
-
执行策略;
以下的各功能的演示,主要体现的是用法,不会所有情况都举例演示,仅提供思路;其中说明主要结合代码,以注释为主:
2.1 重试(Retry)
代码实现:
运行结果(测试的时候,用Release模式或者直接执行编译后的执行文件,不然Debug模式的时候遇见异常会提示,查看结果不方便):
上面逻辑是失败就重试,其实在实际应用场景,通常有一个时间间隔重试,每次重试递增的时间不一样,代码如下:
运行结果如下:
2.2 熔断(Circuit Breaker)
代码实现:
运行结果:
上面这种只是常规熔断方式,Polly还提供高级熔断配置,根据熔断比率进行熔断,更加符合应用场景,通过设置样本收集时间,然后计算收集的业务处理结果比率,如果达到熔断比率就进行熔断。代码如下:
运行效果如下:
2.3 回退(Fallback)
代码实现如下:
运行结果:
当异常发生的时候,也可以指定对应的操作逻辑。
2.4 超时(Timeout )
代码实现:
运行结果:
超时这分为乐观超时(Optimistic timeout)和悲观超时(Pessimistic timeout),乐观超时需要CancellationToken 在业务逻辑中进行取消,而悲观超时没有取消的话,超时了还会继续执行,上面的案例就显示了,当触发超时之后,业务逻辑等待一段时间之后,还会返回结果,这个过程是需要耗费相关性能的;根据需要可以自行选择。乐观超时就不演示了,和正常线程逻辑一样,通过CancellationToken取消即可。
超时策略的最终目的就是考虑到用户体验,及时给用户反馈,不让用户一直处于等待中~~~~
2.5 舱壁隔离(Bulkhead Isolation)
代码实现:
运行效果:
其实在设置策略参数的时候,还可以指定等待队列的数,也就是说当业务执行数达到设置并发数时,还可以继续执行业务,只是这些业务先会进入等待队列中;这里就不详细演示了,后续在API中在具体说明,对于限流这块,放在API那块可能更容易理解,这里就先进了解。
2.6 缓存(Cache)
缓存这块演示的是基于内存的,需要额外引入包Polly.Caching.Memory和Microsoft.Extensions.Caching.Memory,关于MemoryCache的具体细节,可以参考这篇文章(因MemoryCache闹了个笑话)。
代码实现:
运行效果:
关于缓存这块,也是可以集成Redis进行做分布式缓存的。后面的项目分享的时候再详细说,如果小伙伴好奇,可以参照官网,用法和上面一样,只是引用的包不一样而已。
2.7 策略包装( PolicyWrap)
代码及运行效果:目的就是为了组合策略,应对业务逻辑的各种情况。
上述只是演示了常用的策略使用方式,并没有面面俱到,更加详细内容可以参照官网,结合我的演示思路,看官网例子就很容易啦:
官网地址:https://github.com/App-vNext/Polly/wiki/PolicyWrap
总结
关于Polly,就先说到这,后面的Demo或项目中肯定还会用到的,在这里用控制台项目的方式演示,一方面是为了方便,针对某个点好测试,另一方面是为了说明Polly不是针对WebAPI调用采用的,而是根据需要在项目其他任何地方都可以用(好多小伙伴都认为只是用于HttpClient调用API);