Spring AMQP SimpleMessageListenerContainer源码分析

关系图

类说明

InternalConsumer:

BlockingQueueConsumer的内部类,实现了<amqp-client>的DefaultConsumer类,实际的RabbitMQ Client消费者;一个InternalConsumer对应一个queue,非阻塞地从RabbitMQ Server中接收消息。

private final class InternalConsumer extends DefaultConsumer {

	private final String queueName;

	private boolean canceled;

	InternalConsumer(Channel channel, String queue) {
		super(channel);
		this.queueName = queue;
	}

    // 省略...
}


BlockingQueueConsumer

内部类InternalConsumer接收消息,并存放在BolckingQueue<Delivery>中(LinkedBolckingQueue是Java内部提供的阻塞对列),对外提供阻塞方法nextMessage消费消息,形成生产者消费者模式;

prefetchCount参数为LinkedBolckingQueue对列长度,同时也是basicQos,即一个consumer从RabbitMQ Server预取的消息数量,默认为250个。

public BlockingQueueConsumer(ConnectionFactory connectionFactory,
							 MessagePropertiesConverter messagePropertiesConverter,
							 ActiveObjectCounter<BlockingQueueConsumer> activeObjectCounter, AcknowledgeMode acknowledgeMode,
							 boolean transactional, int prefetchCount, boolean defaultRequeueRejected,
							 @Nullable Map<String, Object> consumerArgs, boolean noLocal, boolean exclusive, String... queues) {
	this.connectionFactory = connectionFactory;
	this.messagePropertiesConverter = messagePropertiesConverter;
	this.activeObjectCounter = activeObjectCounter;
	this.acknowledgeMode = acknowledgeMode;
	this.transactional = transactional;
	this.prefetchCount = prefetchCount;
	this.defaultRequeueRejected = defaultRequeueRejected;
	if (consumerArgs != null && consumerArgs.size() > 0) {
		this.consumerArgs.putAll(consumerArgs);
	}
	this.noLocal = noLocal;
	this.exclusive = exclusive;
	this.queues = Arrays.copyOf(queues, queues.length);
	this.queue = new LinkedBlockingQueue<Delivery>(queues.length == 0 ? prefetchCount : prefetchCount * queues.length);
}

AsyncMessageProcessingConsumer

SimpleMessageListenerContainer的内部类,管理BlockingQueueConsumer,实现了Runnable接口,最终由SimpleAsyncTaskExecutor线程池运行;

AsyncMessageProcessingConsumer(BlockingQueueConsumer consumer) {
	this.consumer = consumer;
	this.start = new CountDownLatch(1);
}

负载动态调整逻辑

1默认线程数concurrentConsumers = 1,运行时始终保持开启的消费者数量,即对应的BlockingQueueConsumer数量;

protected int initializeConsumers() {
	int count = 0;
	synchronized (this.consumersMonitor) {
		if (this.consumers == null) {
			this.cancellationLock.reset();
			this.consumers = new HashSet<BlockingQueueConsumer>(this.concurrentConsumers);
			for (int i = 1; i <= this.concurrentConsumers; i++) {
				BlockingQueueConsumer consumer = createBlockingQueueConsumer();
				if (getConsumeDelay() > 0) {
					consumer.setConsumeDelay(getConsumeDelay() * i);
				}
				this.consumers.add(consumer);
				count++;
			}
		}
	}
	return count;
}


2、默认最大线程数maxConcurrentConsumers为空,此时仅维持固定的消费者数量,设置了之后动态增加和减少消费者。
3、默认任意一个线程连续10次接收到消息,且距离上次添加线程超过10秒,则增加新的消费者,可通过设置startConsumerMinInterval、consecutiveActiveTrigger调整;

private void considerAddingAConsumer() {
	synchronized (this.consumersMonitor) {
		if (this.consumers != null
				&& this.maxConcurrentConsumers != null && this.consumers.size() < this.maxConcurrentConsumers) {
			long now = System.currentTimeMillis();
			if (this.lastConsumerStarted + this.startConsumerMinInterval < now) {
				this.addAndStartConsumers(1);
				this.lastConsumerStarted = now;
			}
		}
	}
}


4、默认任意一个线程连续10次接收不到消息,且距离上次关闭线程超过60秒,则移除当前消费者,可通过设置stopConsumerMinInterval、consecutiveIdleTrigger调整;

private void considerStoppingAConsumer(BlockingQueueConsumer consumer) {
	synchronized (this.consumersMonitor) {
		if (this.consumers != null && this.consumers.size() > this.concurrentConsumers) {
			long now = System.currentTimeMillis();
			if (this.lastConsumerStopped + this.stopConsumerMinInterval < now) {
				consumer.basicCancel(true);
				this.consumers.remove(consumer);
				if (logger.isDebugEnabled()) {
					logger.debug("Idle consumer terminating: " + consumer);
				}
				this.lastConsumerStopped = now;
			}
		}
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值