springcloud 熔断_熔断降级之Spring Cloud
发布日期:2021-06-25 19:30:00 浏览次数:3 分类:技术文章

本文共 3613 字,大约阅读时间需要 12 分钟。

Hystrix是Spring Cloud提供的一种带有熔断机制的框架,就跟电路上的闸差不多。它有三种状态:关闭,开启和半开。最开始是关闭状态的,这个时候所有请求都可以通过;如果错误请求达到一定的阈值,就会变成开启状态,就会让所有请求短路,直接返回失败的响应;一段时间后,断路器会变成半开状态,如果下一个请求成功了,就关闭断路器,反之就开启断路器。

Hystrix提供了如下的几个跟circuitBreaker相关的关键参数,来对一个熔断器进行配置:

1、requestVolumeThreshold,该属性用来设置在滚动时间窗中,断路器的最小请求数。例如:默认值 20 的情况下,如果滚动时间窗(默认值 10秒)内仅收到19个请求,即使这19个请求都失败了,断路器也不会打开。

2、sleepWindowInMilliseconds,短路多久以后开始尝试是否恢复,默认5s

3、errorThresholdPercentage,出错百分比阈值,当达到此阈值后,开始短路,默认50%。

3个参数放在一起,所表达的意思就是:

每当20个请求中,有50%失败时,熔断器就会打开,此时再调用此服务,将会直接返回失败,不再调远程服务。直到5s钟之后,重新检测该触发条件,判断是否把熔断器关闭,或者继续打开。

这里面有个很关键点,达到熔断之后,那么后面它就直接不去调该微服务。那么既然不去调该微服务或者调的时候出现异常,出现这种情况首先不可能直接把错误信息传给用户,所以针对熔断我们可以考虑采取降级策略。所谓降级,就是当某个服务熔断之后,服务器将不再被调用,此时客户端可以自己准备一个本地的fallback回调,返回一个缺省值。

1、Hystrix流程分析

edc23f5409222538c5eca1255c794c00.png

上图是Hystrix流程结构图,工作流程主要如下:

1、每次调用创建一个新的HystrixCommand,把依赖调用封装在run()方法中;

2、执行execute()/queue做同步或异步调用;

3、判断熔断器(circuit-breaker)是否打开,如果打开跳到步骤8,进行降级策略,否则继续后续步骤;

4、判断线程池/队列/信号量是否跑满,如果跑满进入降级步骤8,否则继续后续步骤;

5、调用HystrixCommand的run方法,运行依赖逻辑;

a 依赖逻辑调用超时,进入步骤8

6、判断逻辑是否调用成功;

a 返回成功调用结果

b 调用出错,进入步骤8

7、计算熔断器状态,所有的运行状态上报给熔断器,用于统计从而判断熔断器状态;

8、getFallback()降级逻辑;

以下四种情况将触发getFallback调用:

run()方法抛出非HystrixBadRequestException异常

run()方法调用超时

熔断器开启拦截调用

线程池/队列/信号量是否跑满

没有实现getFallback的Command将直接抛出异常

fallback降级逻辑调用成功直接返回

降级逻辑调用失败抛出异常

9、返回执行成功结果;

2、熔断器

e18e05f0cb5cc949a661b80109a38153.png

上图是断路器的状态关系图,当断路器处于打开状态时,如果打开时间超过了我们定义的circuitBreakerSleepWindowInMilliseconds时间(默认5000毫秒),那么断路器会切换到半开状态;如果此时请求继续失败,断路器又变回成打开状态,等待下个circuitBreakerSleepWindowInMilliseconds时间。若请求成功,则断路器变为闭合状态。

3、Hystrix隔离分析

Hystrix隔离方式采用线程/信号的方式,通过隔离限制依赖的并发量和阻塞扩散,官方默认和推荐的是线程池隔离方式。

1)线程隔离

把执行依赖代码的线程与请求线程(如:tomcat线程)分离。通过线程池大小可以控制并发量,当线程池饱和时可以提前拒绝服务,防止依赖问题扩散。线上建议线程池不要设置过大,否则大量堵塞线程有可能会拖慢服务器。

2)信号量隔离

信号量的资源隔离只是起到一个开关的作用,例如,服务X的信号量大小为10,那么同时只允许10个tomcat的线程(此处是tomcat的线程,而不是服务X的独立线程池里面的线程)来访问服务X,其他的请求就会被拒绝,从而达到限流保护的作用。

d6134abb11de6d848eb541ff44939145.png

附:网关是通过线程池隔离,同步的路由方式,适当的线程池大小配置能够防止网关负载过大。

4、Hystrix源码分析

Hystrix主要使用的是RxJava来做异步请求,RxJava是一个异步框架,是对观察者模式的一个应用。

1)@EnableCircuitBreaker标签引入了一个EnableCircuitBreakerImportSelector类,翻译类的名字就是,开启熔断器的导入选择器,导入什么东西呢?看源码:

6e00052ae59cb5da67c3ca56fcf6bbbf.png

翻译类上的注释 “Import a single circuit breaker implementation Configuration”,其实EnableCircuitBreakerImportSelector的作用就是去导入熔断器的配置 。其实Spring中也有类似于JAVA SPI 的加载机制, 即会自动加载 jar包 spring-cloud-netflix-core 中的META-INF/spring.factories 中的Hystrix相关的自动配置类。

注:SPI : 通过将服务的接口与实现分离以实现解耦,提高程序拓展性的机制,达到插拔式的效果 。

30f53028158a709a06a2df4cb1a04a8a.png

HystrixCircuitBreakerConfiguration 就是针对于 Hystrix熔断器的配置

02780b7edd3ec26d9570ba8db3e38c84.png

在该配置类中创建了 HystrixCommandAspect

dd2dcb01fd59e8f85dff39fe21704202.png

HystrixCommandAspect 其实就是对贴了@HystrixCommand标签的方法使用 Aop机制实现处理。代码中通过把目标方法封装成 HystrixInvokable对象,通过CommandExecutor工具来执行目标方法。

HystrixInvokable是用来干嘛的?看源码知道,其实他是一个空行法的接口,他的目的只是用来标记可被执行,那么他是如何创建的我们看代码HystrixInvokable invokable = HystrixCommandFactory.getInstance().create(metaHolder);的create方法

fa1d8a334d7f6d169d334ea97e15d4bd.png

其实是new了一个 GenericCommand 对象,很明显他们是实现关系,跟踪 GenericCommand 的源码

0b486fa7dee34dedf4a6b8b73e4c7bfa.png

它本身对目标方法的正常执行和对 fallback方法的 执行做了实现 。

GenericCommand.this.getCommandAction().execute(…)获取到目标方法并执行,底层会交给 MethodExecutionAction 使用反射去执行方法。

回到 HystrixCommandAspect的methodsAnnotatedWithHystrixCommand方法中,我们看下 CommandExecutor.execute是如何执行的

34dd04cdc4d15e5f1349cf62f9058164.png

这里有两种执行方式 SYNCHRONOUS 异步 ,ASYNCHRONOUS同步,我们先看同步:castToExecutable(invokable, executionType).execute(); 这里代码把HystrixInvokable对象转成 HystrixExecutable并调用execute方法执行,跟踪execute方法进入HystrixCommand.execute方法中

e249db708eacf0f537765b3980563a9c.png

在 HystrixCommand.execute方法中 其实是Future 来异步执行,调用过程中会触发 GenericCommand来完成调用,执行完成后调用 Future.get()方法拿到执行结果 。

在queue()方法中调用的toObservable()方法中,我们可以发现大量类似Observable.defer(new Func0>() {...});方法,里面的逻辑晦涩难懂,这主要是Hystrix是由RxJava实现的,RxJava是一个神奇的框架,用法很简单,但内部实现有点复杂,代码逻辑有点绕,是响应式编程在Java中的一种实现。至于什么是响应式编程,可以用另外一篇文章来介绍。

参考:

https://blog.csdn.net/wangchengming1/java/article/details/93191815

https://blog.csdn.net/wolfcode_cn/article/details/85776226

https://blog.csdn.net/ok449a6x1i6qq0g660fv/article/details/89348394

转载地址:https://blog.csdn.net/weixin_39622901/article/details/111392706 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:python multiprocessing.pool_python – multiprocessing.Pool:何时使用apply,a...
下一篇:随机森林模型_RDKit | 基于随机森林(RF)的机器学习模型预测hERG阻断剂活性

发表评论

最新留言

关注你微信了!
[***.104.42.241]2024年04月22日 02时42分37秒