最近自己看到了SpringCloud微服务实战的Hystrix这一块,就简单的将这一块中的服务降级跟大家说一说。
Hystrix的概念以及其作用
断路器模式源于Martin Fowler的Circuit Breaker一文中。断路器本身是一种开关装置,用于在电路撒谎给你保护线路过载,当线路中有电器发生短路时,该装置能够及时切断故障电路,很好的保护其他电路不受影响。应用到微服务这一块,主要解决的是由于网络延迟等各种故障原因,让服务请求进行降级处理,让服务更加具有容错性。
Hystrix服务降级原理分析
这里先贴出一张官网上,Hystrix服务降级的原理图。
1、创建HystrixCommand和HystrixObservableCommand对象
通过命令模式进行服务调用封装操作,但是这两种对象的返回结果不同:
HystrixCommand返回单一的操作对象Observable;
HystrixObservableCommand返回多个操作结果
2、命令执行
首先介绍一下四种执行方法:
1、execute():该方法通过同步阻塞方法get()获取到queue()产生的Future对象并一致等待结果
2、queue():该方法通过toObservable()产生的原始Observable通过toBlocking()转换成BlockingObservable,并调用其toFuture()方法返回异步对象Future对象;
3、observable():在toObservable()产生原始Observable对象之后,就立即订阅它,让命令马上进行异步执行,并返回一个Observable对象,当调用它的subscribe时,将重新产生结果并通知给订阅者。(观察者-订阅者模式)
4、toObservable():返回最原始的Observable对象,只有通过observer()方法中进行订阅之后,才能真正出发命令的执行流程。
3、 结果是否被缓存
当当前命令的请求缓存功能是开启的,并且该命令缓存命中,那么缓存的结果就立马以Observable对象的形式进行返回。
4、断路器是否打开
打开:Hystrix不会执行命令,而是直接转到fallback处理逻辑
关闭:检查是否有可用资源(线程池、请求队列、信号量是否占满)来执行命令
5、线程池、请求队列、信号量是否占满
当命令相关的线程池、请求队列、信号量已经被占满,Hystrix也不会执行命令,而是直接转到fallback处理逻辑
这里的线程池不是指容器的线程池,而是每个依赖服务的专有线程池。使用到了舱壁模式(Bulkhead Pattern)隔离每个依赖的服务。
6、HystrixCommand.run() 和 HystrixObservableCommand.construct()
Hystrix会根据不同的请求方法去请求所依赖的服务
run():返回单一的结果并产生一个onCompleted的结束通知,或者抛出异常
construct():返回一个Observable对象来发射多个结果,或者通过onError发送错误通知
若上面的两个方法超时请求,同样也会转到fallback处理逻辑
7、计算断路器的健康度
Hystrix会将“成功”、“失败”、“拒绝”、“超时”等消息报告给断路器,断路器维护一组计数器来统计这些数据。通过这些数据会判断是否开启断路器。
8、fallback逻辑处理 == 服务降级
当执行请求命令时,会根据调用命令执行方法的不同从而进行不同的处理
execute():直接抛出异常
queue():正常返回Observable对象,但是在get()获取结果时抛出异常
observer():正常返回Observable,但是在订阅者订阅时,会立即收到onError方法来终止请求
toObservable():正常返回Observable,但是在订阅者订阅时,会收到onError方法来终止请求
9、返回成功的响应
具体返回结果可以参考第二步命令执行过程中的返回结果和那张图片。