问题
最近线上消息积压刚好碰到这个问题。
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队列的时候,并没有设置容量大小,所以是无界队列...基本是不会满的。
总结起来就是:
- rocketMQ用的是ThreadPoolExecutor
- ThreadPoolExecutor只有当任务队列满了才会启动大于核心线程数的新线程
- rocketMQ传给ThreadPoolExecutor的队列是没设置容量的无界队列
- 所以任务队列基本不会满
- 所以ThreadPoolExecutor基本不会新建大于核心线程数的线程
- 所以rocketMQ设置的ConsumeThreadMax是无效的
ps:虽然实际线程数不会达到consumeThreadMax,但该值还是要大于consumeThreadMin,不然mq会判断为报错。
参考:
ThreadPoolExecutor coreSize、maxPoolSize 的一个理解误区
有关无界队列LinkedBlockingQueue:LinkedBlockingQueue
本文揭示了RocketMQ中ConsumeThreadMax设置无效的问题,原因在于其使用的ThreadPoolExecutor中的无界队列导致线程池最大线程数无法达到预期。通过深入剖析ThreadPoolExecutor的工作原理和RocketMQ配置,解释了为何设置无效并提出解决方案。
824

被折叠的 条评论
为什么被折叠?



