Hystrix基础——熔断器、资源隔离、服务降级

资源隔离:
       资源隔离有线程池模式和信号量模式,hystrix默认使用线程池模式;ribbon发起对依赖服务的请求时,由hystrix的HystrixCommand代理实现,并初始化线程池由线程池创建新的线程来处理本次请求;之后的请求在所有核心线程工作饱和情况下先入线程池队列,否则线程池继续创建新的线程处理请求。这种方式要为每个依赖服务申请线程池,有一定的资源消耗,好处是可以应对突发流量(流量洪峰来临时,处理不完可将数据存储到线程池队列里慢慢处理);信号量模式是每次对依赖服务的请求会创建新的线程处理,每创建新的线程信号量+1,请求返回后信号量-1,无法应对流量洪峰的发生。后面会详细介绍线程池和信号量两种模式的区别。

熔断器:
       hystrix判定请求依赖服务超时后开启熔断器,熔断和不熔断的区别就是,调用并请求依赖服务和调用但不请求依赖服务;熔断器可防止请求依赖服务超时情况下系统发生雪崩效应;代码层面可以理解hystrix为每个依赖服务的调用都会分配一个HystrixCommand代理实现,HystrixCommand会维护一个线程池/信号量以及熔断器。熔断器有三种状态:
open:调用依赖服务时不发起请求,而是执行本地服务降级方法;规定时间内会持续open;规定之间过后会进入half-open状态
closed:调用依赖服务时发起请求,请求失败/超时的次数超过阈值则进入open状态并执行本地服务降级方法
half-open:调用依赖服务时发起请求,请求失败/超时则直接进入open状态并执行本地服务降级方法

快速失败之服务降级:
       hystrix熔断器打开后,调用依赖服务时会尝试进行服务的降级处理,保证依赖服务的可用性。另外,线程池队列排满/信号量阈值情况下都会引起对依赖服务的服务降级处理,保证依赖服务的可用性

最后简单说一下超时重试下的场景助于理解:
       超时和重试:ribbon超时后会对当前的节点进行重试,重试一定次数后继续超时则尝试重试其他节点请求处理依赖服务;达到hystrix请求响应的超时条件后开启熔断器,往后请求在规定时间内再次对该依赖服务发起请求将会被熔断,该请求可以走向服务的降级处理;规定时间过后再次发起的请求会被重试,如果再次获取响应超时则继续做超时处理;这里是熔断、资源隔离和快速失败机制所发挥的作用。需要注意的是,配置ribbon的超时时间时,hystrix的超时时间要大于ribbon的超时时间,这样ribbon才能完成请求重试;否则请求会被hiystrix熔断ribbon是无法完成重试的


以下内容引用狼哥的精辟总结,出处:https://www.jianshu.com/p/dc0410558fc9

资源隔离-信号量模式
       在该模式下,接收请求和执行依赖服务在同一个线程内完成,不存在线程上下文切换所带来的性能开销,所以大部分场景应该选择信号量模式,但是在下面这种情况下,信号量模式并非是一个好的选择。比如一个接口中依赖了3个下游:serviceA、serviceB、serviceC,且这3个服务返回的数据互相不依赖,这种情况下如果针对A、B、C的熔断降级使用信号量模式,那么接口耗时就等于请求A、B、C服务耗时的总和,无疑这不是好的方案。

资源隔离-线程池模式
       在该模式下,用户请求会被提交到各自的线程池中执行,把执行每个下游服务的线程分离,从而达到资源隔离的作用。当线程池来不及处理并且请求队列塞满时,新进来的请求将快速失败,可以避免依赖问题扩散。
在信号量模式提到的问题,对所依赖的多个下游服务,通过线程池的异步执行,可以有效的提高接口性能。

优势:
       减少所依赖服务发生故障时的影响面,比如ServiceA服务发生异常,导致请求大量超时,对应的线程池被打满,这时并不影响ServiceB、ServiceC的调用。
如果接口性能有变动,可以方便的动态调整线程池的参数或者是超时时间,前提是Hystrix参数实现了动态调整。

缺点:
       请求在线程池中执行,肯定会带来任务调度、排队和上下文切换带来的开销。
因为涉及到跨线程,那么就存在ThreadLocal数据的传递问题,比如在主线程初始化的ThreadLocal变量,在线程池线程中无法获取

注意:因为Hystrix默认使用了线程池模式,所以对于每个Command,在初始化的时候,会创建一个对应的线程池,如果项目中需要进行降级的接口非常多,比如有上百个的话,不太了解Hystrix内部机制的同学,按照默认配置直接使用,可能就会造成线程资源的大量浪费。

你可能感兴趣的:(Hystrix)