springcloud 熔断_SpringCloud熔断器之Hystrix源剖析

前面我们已经看过了springcloud的注册中心eureka、负载均衡ribbon的源码,本文我们继续看一下springcloud的断路器Hystrix的源码

源码入口

51c8f71b2b684ebcb66e5756ce00dce9.png

进入org.springframework.cloud.netflix.hystrix.EnableHystrix

2d192da64f7f5c32a01f7e8368b69a96.png

进入org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker

2cc5908958fff3bedddd9ceaed74df50.png

可以看到这里就是引入了一个断路器选择器org.springframework.cloud.client.circuitbreaker.EnableCircuitBreakerImportSelector进入里面

99eb08ef7b95229ea2dd941391459b7b.png

可以看到这里就只有一个判断是否启用的方法,我们点进父类org.springframework.cloud.commons.util.SpringFactoryImportSelector中去看看里面做了啥

9a2db52e70fb3c74cf9cc2b1228dc928.png

我们可以看到,在这个里的构造器中初始化了注解的类型,而从上一张图片我们可以知道这个泛型是org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker

在org.springframework.cloud.commons.util.SpringFactoryImportSelector类中,我们看到有一个org.springframework.cloud.commons.util.SpringFactoryImportSelector#selectImports方法,我们看一下这里面都做些啥

46cbb79ee75e55b5e1586225d99afceb.png

可以看到,这里主要就是获取注解的配置属性以及加载自动装载bean的factory,我们继续跟进加载factory的方法

进入org.springframework.core.io.support.SpringFactoriesLoader#loadFactoryNames

c866fab090b9790d4b36d9334480d758.png

087c1b5d867163e591e5758c6a15a8ff.png

可以看到这里主要就是从缓存中获取一下factory,如果没有找到就去指定目录加载,然后放入缓存。接下来我们看一下这个目录中都放了存了什么

486b955fa6d46127eb1abc51eacc2e9e.png

进入org.springframework.cloud.netflix.hystrix.HystrixCircuitBreakerConfiguration

4698615fdfa36d1937d1ea46e281ad5e.png

发现com.netflix.hystrix.contrib.javanica.aop.aspectj.HystrixCommandAspect这个好像有点有点像@HystrixCommand注解哦,咱们点进去看看

29e7ce3662521306d0ad36f6e1c52cc1.png

嗯?看起来着几个注解好像都是aop的啊,作者的注释也是说是这个是用来处理HystrixCommand注解标记的方法的切面。

接下来我们就一起来看看这个切面环绕通知里都做了什么

11b035d4bf995b1d24c4edc217178c12.png

可以看到这个方法里主要做了四件事

1、通过通过joinpoint获取原始方法;

2、通过joinpoint封装方法元信息;

3、获取Hystrix可调用对象;

4、将可调用对象委派出去;

下面我们就重点来关注一下获取可调用对象

进入com.netflix.hystrix.contrib.javanica.command.HystrixCommandFactory#create

624ccbf6baf5e00318a6658262cb16dc.png

进入com.netflix.hystrix.contrib.javanica.command.GenericCommand

eae5bb878de8635acbe43858cbb30d38.png

可以看到,这里有调用了父类的构造方法,而且自己重写了父类的run方法和getFallBack方法,我们接下来看一下它的继承体系图

27d3703689a121f8268c887cb1b1866f.png

可以看到他继承了好几个类,继续跟进父类com.netflix.hystrix.contrib.javanica.command.AbstractHystrixCommand

dbb466b26666787844a3a475a626aa3c.png

继续跟进com.netflix.hystrix.HystrixCommand#HystrixCommand(com.netflix.hystrix.HystrixCommand.Setter)

3d5aa727574c69395346b3733aab0542.png

继续跟进

d6c5dcabf13cca3b20a9f7caf0a665ae.png

继续跟进com.netflix.hystrix.AbstractCommand#AbstractCommand

35839ab01f13b362a77b22c0b0e06553.png

哦,原来这里做了一些初始化动作,这里面有一些熟悉的字眼,线程池?熟悉Hystrix的同学应该都知道,他可以每个方法使用一个线程池,这里的初始化时怎么初始化的呢,咱们点进去看看

bed2947b993a8b6925dd784e268e0dcd.png

进入com.netflix.hystrix.HystrixThreadPool.Factory#getInstance

1ee9e6569b99e3e990fe50b288eafc61.png

0fa3a6f31de7396c91e1bf466900cf6b.png

可以看到,这里就是先从currentHashMap中获取,如果没有再创建一个新的线程池放到map中

继续跟进com.netflix.hystrix.HystrixThreadPool.HystrixThreadPoolDefault#HystrixThreadPoolDefault

ec66dd3de0422afa2e8b6b55486af2cd.png

可以看到这里通过策略模式获取线程池

继续跟进com.netflix.hystrix.strategy.concurrency.HystrixConcurrencyStrategy#getThreadPool

09b74fb511ee5e9b13a6d2e4826b9f62.png

可一个看到这里创建的是jdk原生线程池

从上面这些父类构造器中我们可以知道,其实他就是在父类初始化一些必要参数。

接下来我们回到com.netflix.hystrix.contrib.javanica.aop.aspectj.HystrixCommandAspect#methodsAnnotatedWithHystrixCommand中看看最终是怎么执行的

472e30d1dd31873b49b9d0a672a2b2d5.png

进入 com.netflix.hystrix.contrib.javanica.command.CommandExecutor#execute

7f3697631505f727f6f05b96fa5c180d.png

继续跟进

b8391d72891808bac1dfd4b097e9928e.png

进入com.netflix.hystrix.HystrixExecutable

baa6af4a41d87d8499e06408b1950ca6.png

再进入就是RxJava的内容了,咱们就不继续跟进了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值