1 前言
在 RabbitMQ异常监控及动态控制队列消费的解决方案 中,提供了一种在线动态修改消费者数量的方法,但使用该方法需要及时的监控队列消息的堆积情况,不能做到自动扩展(增加或减少)消费者数量,以应对偶发的消息堆积场景。通过阅读源码,发现RabbitMQ已经提供了一种自动扩展消费者数量的方法,现把具体实现的源码分析进行分享如下。
2 SimpleMessageListenerContainer源码分析
SimpleMessageListenerContainer是监听消息队列的容器,消息队列的每一个监听者都是一个AsyncMessageProcessingConsumer实例。RabbitMQ自动扩展消费者数量的配置及核心逻辑都在该类中,具体源码分析如下。
public class SimpleMessageListenerContainer extends AbstractMessageListenerContainer
implements ApplicationEventPublisherAware {
private static final long DEFAULT_START_CONSUMER_MIN_INTERVAL = 10000;
private static final long DEFAULT_STOP_CONSUMER_MIN_INTERVAL = 60000;
private static final int DEFAULT_CONSECUTIVE_ACTIVE_TRIGGER = 10;
private static final int DEFAULT_CONSECUTIVE_IDLE_TRIGGER = 10;
public static final long DEFAULT_RECEIVE_TIMEOUT = 1000;
public static final int DEFAULT_PREFETCH_COUNT = 1;
public static final long DEFAULT_SHUTDOWN_TIMEOUT = 5000;
// 启动新的消费者最小时间间隔,默认10s,可配置
private volatile long startConsumerMinInterval = DEFAULT_START_CONSUMER_MIN_INTERVAL;
// 停止空闲消费者最小时间间隔,默认60s,可配置
private volatile long stopConsumerMinInterval = DEFAULT_STOP_CONSUMER_MIN_INTERVAL;
// 消费者连续成功消费几条消息时触发considerAddingAConsumer,默认10条,可配置
private volatile int consecutiveActiveTrigger = DEFAULT_CONSECUTIVE_ACTIVE_TRIGGER;
// 消费者连续空闲几次时触发considerStoppingAConsumer,默认10条,可配置
private volatile int consecutiveIdleTrigger = DEFAULT_CONSECUTIVE_IDLE_TRIGGER;
// 并发(或最小)消费者数量,默认1,volatile变量,可在线动态配置
private volatile int concurrentConsumers = 1;
// 最大消费者数量,可配置
private volatile Integer maxConcurrentConsumers;
// 最近一次开启新消费者时间戳
private volatile long lastConsumerStarted;
// 最近一次停止消费者时间戳
private volatile long lastConsumerStopped;
// 消费者从队列获取消息的超时时间,默认1s,可配置
private long receiveTimeout = DEFAULT_RECEIVE_TIMEOUT;
// 监听容器的消费者集合,存放所有活着的消费者
private Set<BlockingQueueConsumer> consumers;
// 消费者监控器,每个消费者都是一个独立的线程,开启、停止消费者等操作时,为线程安全考虑,需要加锁
private final Object consumersMonitor = new Object();