⼋、Hystrix⼯作流程解析
Hystrix内部存在⼀套精细、⾼效和简洁的流程,该流程为实现hystrix的服务降级、故障隔离、访问限流和对被依赖服务运⾏信息的维护奠定了坚实的基础。
Hystrix整体⼯作流程
hystrix整个⼯作流程涉及到熔断器、缓冲、线程池等组件。这些组件分别实现了故障隔离、访问合并、服务降级和访问限流等功能,正是这些组件⾼效密切的配合确保了服务的稳定运⾏。
下⾯是hystrix的整体⼯作流程图:
整个流程可以⼤致归纳为如下⼏个步骤:
1. 创建HystrixCommand或者HystrixObrvableCommand对象
2. 执⾏ Command
3. 检查请求结果是否被缓存
4. 检查是否开启了短路器
5. 检查线程池/队列/maphore 是否已经满
6. 执⾏ struct() or HystrixCommand.run()
7. 计算短路健康状况
8. 调⽤fallback降级机制
9. 返回依赖请求的真正结果
⼀、创建Command对象
HytrixCommand和HystrixObrvableCommand包装了对外部依赖访问的逻辑。整个流程的第⼀个步骤就是实例化HystrixCommand 或者HystrixObrvableCommand对象。在构造这两个Command对象时,可以通过构造⽅法传递任何执⾏过程中需要的参数。
英语课外阅读如果对外部依赖调⽤只返回⼀个结果值,那么可以实例化⼀个HystrixCommand对象
HystrixCommand
command
=
newHystrixCommand
(
当今时代的主题是arg1花历
,
arg2
);
如果在调⽤外部依赖时需要返回多个结果值时,可以实例化⼀个HystrixObrvableCommand对象
满月酒邀请短信
HystrixObrvableCommand
command
=
newHystrixObrvableCommand
(
arg1
,
arg2
);
提神笑话
马峦山⼆、执⾏ Command
Hystrix API提供了四个⽅法来执⾏Command,分别如下:
1. execute()⽅法,调⽤后直接block住,属于同步调⽤,直到依赖服务返回单条结果,或者抛出异常
2. queue()⽅法,返回⼀个Future,属于异步调⽤,后⾯可以通过Future获取单条结果
3. obrve()⽅法,订阅(subscribe)⼀个Obrvable对象,Obrvable代表的是依赖服务返回的结果,获取到⼀个那个代表结果的Obrvable对象的
拷贝对象
4. toObrvable()⽅法,返回⼀个Obrvable对象,如果我们订阅(subscribe)这个对象,就会执⾏command
其中execute()和queue()仅仅对HystrixCommand适⽤,适⽤于外部依赖只返回⼀个结果的情况下
。execute()⽅法调⽤的是HystrixCommand.queue().get()⽅法获取最终的返回值。⽽queue()⽅法调⽤的是
三、检查请求结果是否被缓存
如果开启了Hystrix请求结果缓存功能,并且这个调⽤的结果在缓存中存在,那么hystrix会直接将缓存的结果返回。在使⽤HystrixCommand和HystrixObrvableCommand类封装依赖请求逻辑时,可以通过重载getCacheKey()实现请求结果的缓存。通过实现同类请求结果的缓存,可以在同⼀个请求Context中有效降低对外部依赖的实际调⽤次数。
以下是在两个线程中对外部依赖http请求的流程⽰意图:
结果缓存的好处:
1、在同⼀个请求上下⽂中,可以减少使⽤相同参数请求原始服务的开销。
2、请求缓存在 run() 和 construct() 执⾏之前⽣效,所以可以有效减少不必要的线程开销。
四、检查是否开启了短路器沁园春长沙教案
接下来需要判断熔断器的开启状态。如果断路器被打开了,那么hystrix就不会执⾏这个command,⽽是直接去执⾏fallback降级机制。HystrixCircuitBreaker是Hystrix中实现熔断器功能的核⼼类,HystrixCommand和HystrixObrvableCommand通过与HystrixCircuitBreaker交互实现了熔断器功能的开启和关闭。
下⾯是HystrixCircuitBreaker和Command的交互流程和内部开关控制逻辑:
熔断器开关控制条件:
对外部依赖调⽤的次数满⾜配置的阈值
口技
对外部依赖调⽤发⽣错误的⽐率满⾜配置的阈值
在满⾜以上两个条件时,熔断器打开熔断开关,之后所有对外部依赖调⽤都将被直接断开。在开关打开时长超过试探窗⼝期后,熔断器将尝试放⾏部分外部依赖的调⽤,根据试探的结果决定重新开启或则关闭熔断开关。
五、检查 线程池/队列/maphore 是否已经满
Hystrix引⼊了ThreadPool和maphore两种⽅式实现资源隔离机制。如果command对应的线程池/队列/maphore已经满了,那么也不会执⾏command,⽽是直接去调⽤fallback降级机制
六、执⾏ struct() or HystrixCommand.run()
HystrixCommand和HystrixObrvableCommand封装了外部依赖调⽤。通过重写HystrixCommand的run()⽅法和HystrixObrvableCommand类的construct()⽅法实现外部依赖的调⽤。
HystrixCommand的run()⽅法只返回⼀个请求结果
HystrixObrvableCommand的construct()⽅法返回⼀个Obrvable对象,通过订阅该Obrverable可以获取多个返回结果
如果run()⽅法或则construct()⽅法在执⾏外部依赖请求出现超时,那么请求线程或者调⽤线程将抛出T
imeOutException。Hystrix接下来直接返回调⽤降级⽅法获得的值⽽不管超时后外部依赖实际返回结果。除了通过抛出⼀个InterruptException外没有更好的⽅式中断外部调⽤线程的执⾏,所以建议调⽤外部依赖逻辑添加对InterruptException的处理以便在必要时中断请求线程的执⾏,⽽⽬前很多Http Client的实现并没有很好的⽀持该中断的响应,所以在使⽤Http Client发送http请求时需要合理设置超时时间以免长时间阻塞执⾏线程。
如果外部依赖调⽤正常返回,那么Hystrix metrics将进⾏必要的数据统计,这些统计数据关系到HystrixCircuitBreaker的正确运转。
七、计算短路健康状况
Hystrix会将每⼀个依赖服务的调⽤成功,失败,拒绝,超时,等事件,都会发送给circuit breaker断路器,HystrixCircuitBreaker通过维护⼀系列的counter记录外部依赖请求的执⾏情况。断路器根据维护的这些信息,在符合触发条件下开启断路功能,在条件合适的时候关闭断路开关。如果打开了断路器,那么在⼀段时间内就会直接短路,然后如果在之后第⼀次检查发现调⽤成功了,就关闭断路器。
⼋、调⽤fallback降级机制
在以下⼏种情况中,hystrix会调⽤fallback降级机制:run()或construct()抛出⼀个异常,短路器打开,线程池/队列/maphore满
了,command执⾏超时了。
⼀般在降级机制中,都建议给出⼀些默认的返回值,⽐如静态的⼀些代码逻辑,或者从内存中的缓存中提取⼀些数据,尽量在这⾥不要再进⾏⽹络请求了;
即使在降级中,⼀定要进⾏⽹络调⽤,也应该将那个调⽤放在⼀个HystrixCommand中,进⾏隔离
。
HystrixCommand通过重载getFallback()⽅法或则HystrixObrvableCommand的resumeWithFallback()⽅法实现服务的降级。通过getFallback()⽅法只能返回⼀个结果值,⽽通过resumeWithFallback()⽅法返回的Obrvable对象可以给请求线程返回多个结果值。
如果fallback返回了结果,那么hystrix就会返回这个结果。对于HystrixCommand,会返回⼀个Obrvable对象,其中会发返回对应的结果; 对于HystrixObrvableCommand,会返回⼀个原始的Obrvable对象。