前言
又是好久没在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
切入请求
注意这里feign开启hystrix后代理对象是HystrixInvocationHandler,而不是feign默认的FeignInvocationHandler,进入HystrixInvocationHandler的invoke方法,这里关于为什么会进入invoke方法,本文不过多介绍,本文核心围绕Hystrix线程池部分讲解!HystrixCommand
经过一些列的构造方法
Hystrix线程池其实就是threadPool,但是这个threadPool不是简单java自带的threadPool,而是Hystrix基于threadPool之上自己造的轮子,关于为什么可能是java的threadPool不够Hystrix用吧!Hystrix线程池
Hystrix的线程池是HystrixThreadPool
HystrixThreadPool通过initThreadPool构建出来
本质上就是利用单例工厂创建出来的!我们来看看HystrixThreadPool,
HystrixThreadPool是个接口!
注意这里有个缓存,这里会将每次创建的HystrixThreadPool缓存起来,后面直接通过服务名获取,这里key其实就是feign远程调用的微服务名称!threadPools.put(key, new HystrixThreadPoolDefault(threadPoolKey, propertiesBuilder));
这里往threadPools添加的是HystrixThreadPoolDefault对象!,我们看看这个对象是怎么创建的!创建HystrixThreadPoolDefault
前面说到Hystrix线程池是基于java的ThreadPool从新造的轮子,在HystrixThreadPoolDefault中就能体现出来!
这个创建HystrixThreadPoolDefault的对象其实就是Hystrix中使用的线程池!上面框起来的几行代码就是核心了!
真正创建线程池
HystrixConcurrencyStrategy concurrencyStrategy = HystrixPlugins.getInstance().getConcurrencyStrategy();
在HystrixConcurrencyStrategy类中
注意这里这行代码,以hystrix开头的,这里既是指定线程池中线程的名字,后面会通过这个名字来验证
Thread thread = new Thread(r, "hystrix-" + threadPoolKey.name() + "-" + threadNumber.incrementAndGet());
上面那个图中就有new ThreadPoolExecutor创建线程池的代码,然后将创建好的java线程从给Hystrix进行包装
也就是包装为HystrixThreadPool,那么Hystrix线程从的创建就完成了Hystrix线程池使用
这中间的调用就比较复杂了,本文不会介绍Hystrix的调用链路,我们直接到使用线程池的逻辑!
这里会获取上面创建好的Hystrix线程池!来执行Observable.defer中的call部分代码,这里是使用线程池中的线程,并不再是Http请求的那个线程了!在call方法中最后返回getUserExecutionObservable(_cmd);方法!这个方法就是回调执行Feign部分逻辑,如下!
最后通过HystrixInvocationHandler.this.dispatch.get(method).invoke(args);这行代码切入Feign远程调用逻辑