【SpringCloud】HystrixCommand的threadPoolKey默认值及线程池初始化

本文探究了SpringCloud中HystrixCommand的threadPoolKey默认值和线程池初始化。通过测试发现,当未指定threadPoolKey时,默认使用groupKey,即注解所在类名作为线程池Key。测试展示了当线程池大小为2时,超过并发数的请求会被拒绝并进入fallback。文章详细分析了HystrixCommand的创建过程,解释了threadPoolKey的默认获取和线程池初始化。结论指出,可通过@DefaultProperties和@HystrixCommand指定线程池Key,且动态设置threadPoolKey会导致新线程池的创建,但旧线程池不会被关闭。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

关于threadPoolKey默认值的疑问

使用SpingCloud必然会用到Hystrix做熔断降级,也必然会用到@HystrixCommand注解,@HystrixCommand注解可以配置的除了常用的groupKey、commandKey、fallbackMethod等,还有一个很关键的就是threadPoolKey,就是使用Hystrix线程隔离策略时的线程池Key


/**
 * This annotation used to specify some methods which should be processes as hystrix commands.
 */
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface HystrixCommand {

    /**
     * The command group key is used for grouping together commands such as for reporting,
     * alerting, dashboards or team/library ownership.
     * <p/>
     * default => the runtime class name of annotated method
     *
     * @return group key
     */
    String groupKey() default "";

    /**
     * Hystrix command key.
     * <p/>
     * default => the name of annotated method. for example:
     * <code>
     *     ...
     *     @HystrixCommand
     *     public User getUserById(...)
     *     ...
     *     the command name will be: 'getUserById'
     * </code>
     *
     * @return command key
     */
    String commandKey() default "";

    /**
     * The thread-pool key is used to represent a
     * HystrixThreadPool for monitoring, metrics publishing, caching and other such uses.
     *
     * @return thread pool key
     */
    String threadPoolKey() default "";
    
    ......省略
}

而使用中我们常常只指定fallbackMethod回退方法,而不会指定所有属性,从@HystrixCommand的源码注释来看

  • groupKey的默认值是使用@HystrixCommand标注的方法所在的类名
  • commandKey的默认值是@HystrixCommand标注的方法名,即每个方法会被当做一个HystrixCommand
  • threadPoolKey没有默认值

但threadPoolKey却没有说明默认值,而threadPoolKey是和执行HystrixCommand的线程池直接相关的

所以我的疑问就是,threadPoolKey有默认值吗? 默认值是什么? 执行HystrixCommand的线程池又是怎么初始化的? 可以动态调整吗?

测试论证

测试代码

spring-cloud-example-consumer-ribbon-hystrix-threadpool

测试端点及方式

首先需要启动 spring-cloud-example-eureka-server-standalone注册中心spring-cloud-example-simple-provider服务提供者

再启动 spring-cloud-example-consumer-ribbon-hystrix-threadpool

测试端点

http://127.0.0.1:20006/testDefaultThreadPoolKey

http://127.0.0.1:20006/testDefaultThreadPoolKey2

testDefaultThreadPoolKey 和 testDefaultThreadPoolKey2 是同一个service的两个方法,分别使用@HystrixCommand指定fallback方法

线程池大小设置为2,且不使用队列暂存,服务提供方sleep 30秒,通过chrome多窗口调用 /testDefaultThreadPoolKey 端点

或同时调用 /testDefaultThreadPoolKey/testDefaultThreadPoolKey2 端点
通过大于线程池最大值的请求被线程池拒绝进入fallback,判断线程池是方法级,还是类级的,以及threadPoolKey默认值

注意:

使用firefox浏览器测试有问题,多标签页必须等待一个GET请求完成,才能继续下一个,测不出并发的效果。

一开始以为是程序上的限制,后来才发现是浏览器,使用chrome问题解决

线程池配置

hystrix.threadpool.default.coreSize = 2
hystrix.threadpool.default.maximumSize = 2
hystrix.threadpool.default.maxQueueSize = -1

线程池的coreSizemaximumSize都设置为2(1.5.9版本后才添加maximumSize),且线程池队列大小为-1,即使用SynchronousQueue

Hystrix线程池的其它属性: Hystrix Thread Pool Properties

测试结果

677054-20181114095005226-134863852.png

chrome浏览器连续GET请求调用6次,分别调用3次 /testDefaultThreadPoolKey,3次 /testDefaultThreadPoolKey2,以绿色线问分隔,可见前两次调用成功,后4次均直接拒绝,进入fallback

具体异常信息为:

java.util.concurrent.RejectedExecutionException: Task java.util.concurrent.FutureTask@6d72dcf rejected from java.util.concurrent.ThreadPoolExecutor@431bfebc[Running, pool size = 2, active threads = 2, queued tasks = 0, completed tasks = 1]

线程池大小为2起到了作用,将大于并发数的请求拒绝了,并且无论是只调用 /testDefaultThreadPoolKey,还是轮询调用 /testDefaultThreadPoolKey/testDefaultThreadPoolKey2 ,测试结果都是这样。再根据hystrix线程的名字 hystrix-ConsumerRibbonHystrixThreadPoolService-n,可以猜想:Hystrix的 threadPoolKey是和hystrixCommand执行的类相关的,可能一个类使用一个线程池,所以两个service方法才会共用线程池

原理分析

HystrixCommandAspect

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值