对于hystrix入门使用的看我之前写的另一篇文章,这里是对于hystrix的原理进行分析
基本概念及工作流程
hystrix是解决服务降级和服务熔断的组件。
服务雪崩:在下图中,如果H服务调用超时,而此时我们没有做降级/熔断处理,此时就会阻塞导致c服务不可用,慢慢积累也会导致A服务也不可用。从而导致整个服务不可用,这就是所谓的服务雪崩
至于怎么使用hystrix的降级和熔断,可以看我前面写的入门篇。
hystrix作为一个熔断器来进行服务熔断,该熔断器存在三种状态:关闭(closed)、开启(open)、半开(half open)。
1、其中默认是关闭,
2、当访问同一个接口超过设定阈值并且错误次数超过设置错误阈值时,就会打开熔断机制,状态从
closed->open(
默认失败比例阀值是50%,请求次数最少不低于20次,默认时间窗口为10s。即在连续的10s内接收的请求(请求数大于20)失败率大于0.5,则开启熔断器)(可以自己进行设置),当进入开启状态后会休眠5秒,然后进入半开状态(进入半开状态看是否可以重新恢复到关闭状态)该期间都是走降级方法
3、当熔断器开启后休眠5s后进入半开状态,试图放进来一些请求,如果这些请求成功,此时则熔断器进入关闭状态,服务可以不用调用降级方法直接走原来的方法。如果失败则重新进入开启状态重新来一遍
上面对于熔断器的状态进行说明,下面对于熔断器的工作机制进行说明:
我们每次创建一个command时会经过下面几个步骤:
1、判断熔断器是否开启,如果开启直接走降级方法。结束2、如果熔断器没开启,看线程池是否满了(满了会走拒绝策略),如果被线程池拒绝了此时会走降级方法,并且会通知Metrics,Metrics会根据收集到的信息判断是否开启熔断器
3、如果线程数充足,此时会直接执行该原生方法,如果其方法执行失败(出现错误/异常)此时会走降级方法,并通知Metrics
4、如果程序执行没出错/异常,但执行时间超时,此时也会直接走降级方法,并通知Metrics。(这里可以自己设置超时时间)
总结:走降级方法(服务降级)请求:
1、服务熔断情况(熔断器开启)
2、线程池/信号量满了(默认使用的是线程池模式)两者的具体区别看:https://blog.csdn.net/qq_35599414/article/details/109318502(线程隔离的机制是用于限流的)
3、代码出错/异常
4、超时
而2、3、4种情况会通知Metrics,Metrics会根据相应的阈值来判断是否开启熔断器(进行服务熔断)。
2、原理分析
注意:原理分析应该围绕@EnableCircultBreaker和@HystrixCommand注解为主要切入点。Hystrix中使用aop、响应式编程等
这里我不打算搬源码,因为hystrix中大量使用rxjava包,其中大量使用响应式编程。响应式编程的风格比较难懂,难分析。这里直接给出整个的源码流程图,该图需要配合运行机制图观看
其中hystrix是对于HystrixCommandAspect类作为切面,并且以methodsAnnotatedWithHystrixCommand方法作为切面处理方法进行环绕round通知。后面根据调用GenericCommand的run方法(正常方法),getFallback方法(降级方法)进行相应处理
其中有个Metrics的调查结果数据统计中心,该数据统计中心会根据失败的次数来统计其阈值,达到一定值时则会开启熔断器。
其中的AbstractCommand中会拿到我们@HystrixCommand的线程池相关信息进行初始化一个线程池,用于后面的线程池隔离。(下面该图这里是结合ribbon进行配置,也可以配合feign进行配置)
熔断器是可以强制打开的(通过配置)
熔断器的状态切换:
在熔断器中需要明白一个概念:滑动窗口
我们上面说了熔断器的相应的三个状态:
hystrix作为一个熔断器来进行服务熔断,该熔断器存在三种状态:关闭(closed)、开启(open)、半开(half open)。
1、其中默认是关闭,
2、当访问同一个接口超过设定阈值并且错误次数超过设置错误阈值时,就会打开熔断机制,状态从
closed->open(
默认失败比例阀值是50%,请求次数最少不低于20次,默认时间窗口为10s。即在连续的10s内接收的请求(请求数大于20)失败率大于0.5,则开启熔断器)(可以自己进行设置),当进入开启状态后会休眠5秒,然后进入半开状态(进入半开状态看是否可以重新恢复到关闭状态)该期间都是走降级方法
3、当熔断器开启后休眠5s后进入半开状态,试图放进来一些请求,如果这些请求成功,此时则熔断器进入关闭状态,服务可以不用调用降级方法直接走原来的方法。如果失败则重新进入开启状态重新来一遍
而第2步中的10s则是一个时间窗口。而滑动窗口即指以10s为单位进行时间上的滑动取值。下面是以默认的10秒的时间窗口模拟的滑动窗口说明
hystrix的一些常用相关配置
参数
作用
备注
circuitBreaker.errorThresholdPercentage
失败率达到多少百分比后熔断 默认值:50
主要根据依赖重要性进行调整
circuitBreaker.forceClosed
是否强制关闭熔断 如果是强依赖,应该设置为true circuitBreaker.requestVolumeThreshold
熔断触发的最小个数/10s 默认值:20 circuitBreaker.sleepWindowInMilliseconds
熔断多少秒后去尝试请求 默认值:5000 commandKey
默认值:当前执行方法名 coreSize
线程池coreSize 默认值:10
execution.isolation.semaphore.maxConcurrentRequests
信号量最大并发度 SEMAPHORE模式有效,默认值:10 execution.isolation.strategy
隔离策略,有THREAD和SEMAPHORE 默认使用THREAD模式,以下几种可以使用SEMAPHORE模式:
- 只想控制并发度
- 外部的方法已经做了线程隔离
- 调用的是本地方法或者可靠度非常高、耗时特别小的方法(如medis)
execution.isolation.thread.interruptOnTimeout
是否打开超时线程中断 THREAD模式有效 execution.isolation.thread.timeoutInMilliseconds
超时时间 默认值:1000
在THREAD模式下,达到超时时间,可以中断
在SEMAPHORE模式下,会等待执行完成后,再去判断是否超时
execution.timeout.enabled
是否打开超时 fallback.isolation.semaphore.maxConcurrentRequests
fallback最大并发度 默认值:10 groupKey
表示所属的group,一个group共用线程池 默认值:getClass().getSimpleName();
maxQueueSize
请求等待队列 默认值:-1
如果使用正数,队列将从SynchronizeQueue改为LinkedBlockingQueue
hystrix.command.default.metrics.rollingStats.timeInMilliseconds 设置统计的时间窗口值的,毫秒值 circuit break 的打开会根据1个rolling window的统计来计算。若rolling window被设为10000毫秒,则rolling window会被分成n个buckets,每个bucket包含success,failure,timeout,rejection的次数的统计信息。默认10000 hystrix.command.default.metrics.rollingStats.numBuckets 设置一个rolling window被划分的数量 hystrix.command.default.metrics.healthSnapshot.intervalInMilliseconds 记录health 快照(用来统计成功和错误绿)的间隔,默认500ms
由于现在的hystrix已经被功能更加强大的sentinel替代,本文就不对其源码做过多解读,知道上面的这些原理,应付面试问题已经不大了。
后面对于阿里的sentinel在仔细分析其源码实现。hystrix就到此结束