NET Core微服务之路:弹性和瞬态故障处理库Polly的介绍

NET Core微服务之路:弹性和瞬态故障处理库Polly的介绍

前言

上一节中我们介绍了Ocelot的常见使用配置,通过json配置文件,实现API网关的请求处理。和一个使用DownStream扩展下游中间件,来实现Http转RPC的简单实现,功能不算强大,但可以作为一个思路,根据自己的RestFul或业务需求来规范下游中间件的处理功能,也有幸被张队收录,十分感谢。
我们知道,Consul、Etcd、Zookeeper等等这些注册中心都有健康检查的机制,用于检查服务节点的状态,是200,还是非200。但是,这种检测是粗粒度的,她只能检测节点的健康状态,却不能检测接口的健康状态,毕竟细粒度的控制太多由业务环境支配,无法统一化和标准化。本节我们介绍如何在接口(或方法)中如何实现健康状态的检测,其实也就是对某个接口的故障保护。
 
先来了解两个重要的名词定义。
 

瞬态故障:

一种仅短暂影响电气设备的介电性能,且可在短时间内自行恢复的故障;电力系统中90%以上的故障都是瞬态故障或由瞬态故障扩大的--来自百度百科。
很难理解吧,没关系,我们换一个解释方法:
当你有一台服务器,服务上运行着一个“秒杀”系统,理论测试下承载的最大并发数是10W,而当实际运行时,瞬间涌入的请求量达到了1000W,如果你没做前置消峰处理(比如使用队列),服务器立马宕机,甚至烧毁的可能性。
再或者,这台服务器的电压是220V,运行电流是10A,如果服务器电源没做瞬时电流保护处理,那么电源第一个被烧坏,然后是CPU,接着是主板,再然后是硬盘,等等不可恢复的灾难。
这种故障是瞬间的,一般都在一秒以内,甚至微秒内发生,一旦出现,如果没有保护错误,那么必将造成重大灾难。
 

过载故障:

在我们的家用电箱中,都会有这么一个重要的器件,如下图所示(它叫空开,也叫断路器),当电流或电压超过断路器的额定工作范围,便会自动断开,从常闭状态改变为常开状态,阻断整个线路的流通情况(同样称之为过载保护)
我们知道,我国规定的市电压是AC220V,50HZ,工业电压是AC380V,50HZ。当输入电压超过这个标准,断路器(比如额定输入AC220V,50HZ,60A,而实际输入AC300V,50HZ,100A)将会断开不合格的输入,达到保护的目的。
切换到我们的软件系统中,比如我们规定一台服务器的最大承载并发数是10W范围,超过这个范围服务器将会运行缓慢、甚至宕机。通过某个软件、或中间件、或物理设备控制着这个输入端,当输入量超过这个范围值,这个输入端将自动断开,达到保护服务的目的。
 
咋一看,瞬态故障和过载故障的意义都差不多,都是为了控制和防止过高或过大的输入,其实不然
从时间点:瞬态故障的动作范围极短,远远超过你眨眼睛的速度。而过载故障有可能是长时间的、超过这个额定范围的输入。
从发生点:瞬态故障发生在“秒杀”、“抢购”等瞬间存在的高并发系统中,而过载故障一般均是设计承载和实际承载不符造成的。
从输入量:瞬态故障的输入量一般是正常输入量的十几倍(电气中甚至上百倍),而过载故障一般是正常范围的几倍,最高也就是几十倍(这都很吓人了)。
 
好了,理解了上面两个主要故障,接下来我们看看有没有什么技术可以减少这种故障的出现的几率(或保护我们的整个系统)。
 

Polly介绍

我们来介绍一款强大的库Polly,Polly是一种.NET 弹性瞬态故障处理库,允许我们以非常顺畅和线程安全的方式来执诸如行重试,断路,超时,故障恢复等策略,并且已经被.NET基金会认可的弹性和瞬态处理库。支持目标.NET Framework 4.5+和.NET Core1.0+以上的基础框架库。
 

安装最新的Polly库

目前最新的官方库是7.0.3,如下所示。
(我喜欢在不同的操作系统上得到相同的开发体验,jetbrains帮我实现了)
 

Polly故障策略(措施)

该库目前按照官方的文档,已经实现了七种弹性策略。戳我查看原文( https://github.com/App-vNext/Polly#resilience-policies
重试策略:许多故障是暂时性的、并且可以在短时间延迟后可以自行纠正:Maybe it's just a blip。
断路器:断路器策略针对当系统繁忙时(或者系统出现故障),快速响应失败总比让用户一直等待更好:Stop doing it if it hurts。
超时:超时策略针对的条件是超过一定的等待时间,如果还未响应,视为超时,保证调用者不必等待到执行超时:Give that system a break。
隔离:隔离针对的条件是当进程出现故障时,多个失败一直在主机中对资源(例如线程/ CPU)一直占用,下游系统故障也可能导致上游失败,这些风险都将造成严重的后果:One fault shouldn't sink the whole ship。
缓存:缓存策略针对的条件是数据不会很频繁的进行更新,为了避免系统过载,首次加载数据时将响应数据进行缓存,如果缓存中存在则直接从缓存中读取:You've asked that one before
回退:不管重试多次,操作仍然会失败,也就是说,当发生这样的事情时我们打算做什么,撤销之前的操作等等都可以:Degrade gracefully。
策略包装:策略包装针对的条件是不同的故障需要不同的策略,也就意味着,可以弹性灵活的组合不同的策略来实现不同的故障保护措施:Defence in depth。
 

一个简单的异常

一般我们在处理异常的时候,都会习惯性用try.catch来处理,比如这样一个不能除以0的数学异常
try
{
    var z = 0;
    var r = 1 / z;
}
catch (DivideByZeroException ex)
{
    throw ex;
}

很友好,也很直观。但假如这不是一个除以0的数学异常,而只是一个其他异常,并且需要我们调用端通过重试或者等待一段时间后才能正常调用的处理呢,比如一个异步的操作方法,我不能将上面的代码加上个for循环,或者调个线程阻塞一下吧,不管理论上为了目的和结果是可以这样写,我们重试10次,可以写成这样。

for (int i = 0; i < 10; i++)
{
    try
    {
        var z = 0<
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值