0
点赞
收藏
分享

微信扫一扫

Hystrix线程池创建,调用


前言

又是好久没在CSDN上发布文章了,主要是最近比较忙,技术部分没有可以输出的,今天周末,又捡起了断断续续的源码进行分析,我们在使用Feign的时候有知道Hystrix有线程池隔离和信号量隔离,相关场景请看陈年旧文​​Feign远程调用丢失请求头​​、​​Feign配置拦截器后直接触发Hystrix服务熔断
​,那么本文就开看看这里的线程池隔离策略中的线程池是怎么创建的,关于Hystrix线程池配置这里就不过多讲解了,随便搜搜多有,但是关于这个Hystrix线程池怎么创建的,缺没找到相关文章!

源码分析

本文是建立在通过Feign能发起远程调用,且配置了feign开启hystrix,Hystrix设置默认线程池隔离策略的代码环境之上的!
基本配置如下!

feign:
hystrix:
enabled: true
client:
config:
#将调用的微服务名称改成default就配置成全局的了
default:
#connectTimeout: 2000
#readTimeout: 5000
loggerLevel: BASIC
default-to-properties: true #默认是否properties配置文件配置优先

hystrix:
command:
default:
execution:
timeout:
enabled: true
isolation:
thread:
timeoutInMilliseconds: 3600000

切入请求

Hystrix线程池创建,调用_分布式


注意这里feign开启hystrix后代理对象是HystrixInvocationHandler,而不是feign默认的FeignInvocationHandler,进入HystrixInvocationHandler的invoke方法,这里关于为什么会进入invoke方法,本文不过多介绍,本文核心围绕Hystrix线程池部分讲解!HystrixCommand

Hystrix线程池创建,调用_java_02


经过一些列的构造方法

Hystrix线程池创建,调用_远程调用_03


Hystrix线程池创建,调用_线程池_04


Hystrix线程池创建,调用_线程池_05


Hystrix线程池其实就是threadPool,但是这个threadPool不是简单java自带的threadPool,而是Hystrix基于threadPool之上自己造的轮子,关于为什么可能是java的threadPool不够Hystrix用吧!Hystrix线程池

Hystrix的线程池是HystrixThreadPool

Hystrix线程池创建,调用_java_06


HystrixThreadPool通过initThreadPool构建出来

Hystrix线程池创建,调用_java_07


本质上就是利用单例工厂创建出来的!我们来看看HystrixThreadPool,

Hystrix线程池创建,调用_分布式_08


HystrixThreadPool是个接口!

Hystrix线程池创建,调用_线程池_09


注意这里有个缓存,这里会将每次创建的HystrixThreadPool缓存起来,后面直接通过服务名获取,这里key其实就是feign远程调用的微服务名称!threadPools.put(key, new HystrixThreadPoolDefault(threadPoolKey, propertiesBuilder));

这里往threadPools添加的是HystrixThreadPoolDefault对象!,我们看看这个对象是怎么创建的!创建HystrixThreadPoolDefault

Hystrix线程池创建,调用_分布式_10


前面说到Hystrix线程池是基于java的ThreadPool从新造的轮子,在HystrixThreadPoolDefault中就能体现出来!

这个创建HystrixThreadPoolDefault的对象其实就是Hystrix中使用的线程池!上面框起来的几行代码就是核心了!

真正创建线程池

HystrixConcurrencyStrategy concurrencyStrategy = HystrixPlugins.getInstance().getConcurrencyStrategy();

Hystrix线程池创建,调用_分布式_11


Hystrix线程池创建,调用_线程池_12


在HystrixConcurrencyStrategy类中

Hystrix线程池创建,调用_分布式_13


注意这里这行代码,以hystrix开头的,这里既是指定线程池中线程的名字,后面会通过这个名字来验证

Thread thread = new Thread(r, "hystrix-" + threadPoolKey.name() + "-" + threadNumber.incrementAndGet());

上面那个图中就有new ThreadPoolExecutor创建线程池的代码,然后将创建好的java线程从给Hystrix进行包装

Hystrix线程池创建,调用_分布式_14


也就是包装为HystrixThreadPool,那么Hystrix线程从的创建就完成了Hystrix线程池使用

这中间的调用就比较复杂了,本文不会介绍Hystrix的调用链路,我们直接到使用线程池的逻辑!

Hystrix线程池创建,调用_远程调用_15


这里会获取上面创建好的Hystrix线程池!来执行Observable.defer中的call部分代码,这里是使用线程池中的线程,并不再是Http请求的那个线程了!在call方法中最后返回getUserExecutionObservable(_cmd);方法!这个方法就是回调执行Feign部分逻辑,如下!

Hystrix线程池创建,调用_分布式_16

Hystrix线程池创建,调用_分布式_17

Hystrix线程池创建,调用_线程池_18


最后通过HystrixInvocationHandler.this.dispatch.get(method).invoke(args);这行代码切入Feign远程调用逻辑

Hystrix线程池创建,调用_分布式_19


举报

相关推荐

0 条评论