Springboot RabbitMq源码解析之consumer管理和AmqpEvent

Springboot RabbitMq源码解析之配置类
Springboot RabbitMq源码解析之消息发送
Springboot RabbitMq源码解析之消费者容器SimpleMessageListenerContainer
上一篇文章Springboot RabbitMq源码解析之消费者容器SimpleMessageListenerContainer主要讲了SimpleMessageListenerContainer的启动和AsyncMessageProcessingConsumer对消息的接收和处理,这一篇文章解析的内容是consumer管理和AmqpEvent,对上一篇文章中没有提到和展开的地方做补充。

一、consumer状态管理

在AsyncMessageProcessingConsumer#run方法中根据需要对BlockingQueueConsumer类型的成员变量consumer进行了管理。

1. BlockingQueueConsumer#start

对consumer进行启动,做好接受消息的准备

public void start() throws AmqpException {
	if (logger.isDebugEnabled()) {
		logger.debug("Starting consumer " + this);
	}

	this.thread = Thread.currentThread();

	try {
		this.resourceHolder = ConnectionFactoryUtils.getTransactionalResourceHolder(this.connectionFactory,
				this.transactional);
		this.channel = this.resourceHolder.getChannel();
		addRecoveryListener();
	}
	catch (AmqpAuthenticationException e) {
		throw new FatalListenerStartupException("Authentication failure", e);
	}
	this.consumer = new InternalConsumer(this.channel);
	this.deliveryTags.clear();
	this.activeObjectCounter.add(this);

	// mirrored queue might be being moved
	int passiveDeclareRetries = this.declarationRetries;
	this.declaring = true;
	do {
		if (cancelled()) {
			break;
		}
		try {
			attemptPassiveDeclarations();
			if (passiveDeclareRetries < this.declarationRetries && logger.isInfoEnabled()) {
				logger.info("Queue declaration succeeded after retrying");
			}
			passiveDeclareRetries = 0;
		}
		catch (DeclarationException e) {
			if (passiveDeclareRetries > 0 && this.channel.isOpen()) {
				if (logger.isWarnEnabled()) {
					logger.warn("Queue declaration failed; retries left=" + (passiveDeclareRetries), e);
					try {
						Thread.sleep(this.failedDeclarationRetryInterval);
					}
					catch (InterruptedException e1) {
						this.declaring = false;
						Thread.currentThread().interrupt();
						this.activeObjectCounter.release(this);
						throw RabbitExceptionTranslator.convertRabbitAccessException(e1);
					}
				}
			}
			else if (e.getFailedQueues().size() < this.queues.length) {
				if (logger.isWarnEnabled()) {
					logger.warn("Not all queues are available; only listening on those that are - configured: "
							+ Arrays.asList(this.queues) + "; not available: " + e.getFailedQueues());
				}
				this.missingQueues.addAll(e.getFailedQueues());
				this.lastRetryDeclaration = System.currentTimeMillis();
			}
			else {
				this.declaring = false;
				this.activeObjectCounter.release(this);
				throw new QueuesNotAvailableException("Cannot prepare queue for listener. "
						+ "Either the queue doesn't exist or the broker will not allow us to use it.", e);
			}
		}
	}
	while (passiveDeclareRetries-- > 0 && !cancelled());
	this.declaring = false;

	if (!this.acknowledgeMode.isAutoAck() && !cancelled()) {
		// Set basicQos before calling basicConsume (otherwise if we are not acking the broker
		// will send blocks of 100 messages)
		try {
			this.channel.basicQos(this.prefetchCount);
		}
		catch (IOException e) {
			this.activeObjectCounter.release(this);
			throw new AmqpIOException(e);
		}
	}


	try {
		if (!cancelled()) {
			for (String queueName : this.queues) {
				if (!this.missingQueues.contains(queueName)) {
					consumeFromQueue(queueName);
				}
			}
		}
	}
	catch (IOException e) {
		throw RabbitExceptionTranslator.convertRabbitAccessException(e);
	}
}

主要的工作有以下:
(1)consumer属性封装
BlockingQueueConsumer也有一个consumer属性,为InternalConsumer类型,有channel封装而来。
(2)queue声明
queue的声明是一个失败重试的循环机制,用一个表示最大重试次数的成员变量passiveDeclareRetries,用成员变量declaring表示正在声明中。使用失败重试的原因如注释所言,主要是针对镜像队列的场景,当然其它时候的声明也有可能抛出异常。
(3)设置basicQos
在不是自动ack的场景下,需要设置basicQos进行并行处理闲置,在规定数目的消息没有被ack前,进行阻塞,不再消费新的消息。
(4)启动消费者,并返回标志,将消费者标志和队列加入键值对。

2. BlockingQueueConsumer#stop

用于终止BlockingQueueConsumer,不在对rabbitmq进行消费。

public void stop() {
	if (this.abortStarted == 0) { // signal handle delivery to use offer
		this.abortStarted = System.currentTimeMillis();
	}
	if (this.consumer != null && this.consumer.getCha
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值