RocketMQ设置的ConsumeThreadMax无效

本文揭示了RocketMQ中ConsumeThreadMax设置无效的问题,原因在于其使用的ThreadPoolExecutor中的无界队列导致线程池最大线程数无法达到预期。通过深入剖析ThreadPoolExecutor的工作原理和RocketMQ配置,解释了为何设置无效并提出解决方案。

问题

最近线上消息积压刚好碰到这个问题。

RocketMQ设置的ConsumeThreadMax无效,线程数只会达到ConsumeThreadMin值。

回答

ConsumeMessageConcurrentlyService
public class ConsumeMessageConcurrentlyService implements ConsumeMessageService {
    private static final InternalLogger log = ClientLogger.getLog();
    private final DefaultMQPushConsumerImpl defaultMQPushConsumerImpl;
    private final DefaultMQPushConsumer defaultMQPushConsumer;
    private final MessageListenerConcurrently messageListener;
    private final BlockingQueue<Runnable> consumeRequestQueue;
    private final ThreadPoolExecutor consumeExecutor;
    private final String consumerGroup;
    private final ScheduledExecutorService scheduledExecutorService;
    private final ScheduledExecutorService cleanExpireMsgExecutors;

    public ConsumeMessageConcurrentlyService(DefaultMQPushConsumerImpl defaultMQPushConsumerImpl, MessageListenerConcurrently messageListener) {
        this.defaultMQPushConsumerImpl = defaultMQPushConsumerImpl;
        this.messageListener = messageListener;
        this.defaultMQPushConsumer = this.defaultMQPushConsumerImpl.getDefaultMQPushConsumer();
        this.consumerGroup = this.defaultMQPushConsumer.getConsumerGroup();
        this.consumeRequestQueue = new LinkedBlockingQueue();
        this.consumeExecutor = new ThreadPoolExecutor(
    this.defaultMQPushConsumer.getConsumeThreadMin(), 
    this.defaultMQPushConsumer.getConsumeThreadMax(), 
    60000L, 
    TimeUnit.MILLISECONDS, 
    this.consumeRequestQueue, 
    new ThreadFactoryImpl("ConsumeMessageThread_"));
        this.scheduledExecutorService = Executors.newSingleThreadScheduledExecutor(new ThreadFactoryImpl("ConsumeMessageScheduledThread_"));
        this.cleanExpireMsgExecutors = Executors.newSingleThreadScheduledExecutor(new ThreadFactoryImpl("CleanExpireMsgScheduledThread_"));
    }

RocketMQ的线程池是ThreadPoolExecutor,线程池的核心线程数等于mq设置的最小线程数,线程池的最大线程数等于mq设置的最大线程数。

即:ThreadPoolExecutor.corePoolSize == RocketMQ.consumeThreadMin

ThreadPoolExecutor.maximumPoolSize == RocketMQ.consumeThreadMax

所以问题变更为
ThreadPoolExecutor.maximumPoolSize不生效!ThreadPoolExecutor的实现逻辑是:当前线程数等于核心线程数,任务会被扔进队列里面,只有当队列满了,才会新起线程,进而达到最大线程数。然而MQ在new队列的时候,并没有设置容量大小,所以是无界队列...基本是不会满的

总结起来就是:

  1. rocketMQ用的是ThreadPoolExecutor
  2. ThreadPoolExecutor只有当任务队列满了才会启动大于核心线程数的新线程
  3. rocketMQ传给ThreadPoolExecutor的队列是没设置容量的无界队列
  4. 所以任务队列基本不会满
  5. 所以ThreadPoolExecutor基本不会新建大于核心线程数的线程
  6. 所以rocketMQ设置的ConsumeThreadMax是无效的

ps:虽然实际线程数不会达到consumeThreadMax,但该值还是要大于consumeThreadMin,不然mq会判断为报错。

参考:

ThreadPoolExecutor coreSize、maxPoolSize 的一个理解误区

有关无界队列LinkedBlockingQueue:LinkedBlockingQueue

原文:RocketMQ设置的ConsumeThreadMax无效
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值