(18)不重启服务动态停止、启动RabbitMQ消费者

我们在消费RabbitMQ消息的过程中,有时候可能会想先暂停消费一段时间,然后过段时间再启动消费者,这个需求怎么实现呢?我们可以借助RabbitListenerEndpointRegistry这个类来实现,它的全类名是org.springframework.amqp.rabbit.listener.RabbitListenerEndpointRegistry,通过这个类可以实现全部队列消息的启动、停止消费,也可以实现指定队列消息的启动、停止消费。具体的原因感兴趣的话可以参考一下我前面的这篇博客(17)不重启服务动态调整RabbitMQ消费者数量,里面有相应的源码分析。

停止、启动全部队列消费

RabbitListenerEndpointRegistry类提供了start()方法和stop()方法,可以看到底层都是通过调用getListenerContainers()获取到所有队列的消费监听容器列表,然后遍历挨个调用对应的start()方法和stop()方法。

java 复制代码
	@Override
	public void start() {
		for (MessageListenerContainer listenerContainer : getListenerContainers()) {
			startIfNecessary(listenerContainer);
		}
	}

	@Override
	public void stop() {
		for (MessageListenerContainer listenerContainer : getListenerContainers()) {
			listenerContainer.stop();
		}
	}

我们只需要获取到RabbitListenerEndpointRegistry对象,然后调用其start()方法和stop()方法即可实现启动/停止所有队列消费。

实现代码如下所示:

java 复制代码
@Resource
RabbitListenerEndpointRegistry rabbitListenerEndpointRegistry;

@RequestMapping(value = "/startStopAllConsumer")
@ApiOperation(value = "启动/暂停全部队列消息消费")
public Response startStopAllConsumer(@RequestParam(value = "consumeSwitch", required = true) boolean consumeSwitch) {
	log.info("启动/暂停全部队列消息消费,consumeSwitch:{}",consumeSwitch);
	if(consumeSwitch){
		rabbitListenerEndpointRegistry.start();
	}else {
		rabbitListenerEndpointRegistry.stop();
	}
	return Response.success();
}

传入开关参数为false,会停止所有队列消费者消费,调用后控制台看到如下日志

2023-09-04 19:43:11.480 +0800 [TID: N/A] [http-nio-8080-exec-4] INFO c.b.t.m.p.w.PayCashierMockController:67 - 启动/暂停全部队列消息消费,consumeSwitch:false

2023-09-04 19:43:11.556 +0800 [TID: N/A] [http-nio-8080-exec-4] INFO o.s.a.r.l.SimpleMessageListenerContainer:586 - Waiting for workers to finish.

2023-09-04 19:43:12.352 +0800 [TID: N/A] [http-nio-8080-exec-4] INFO o.s.a.r.l.SimpleMessageListenerContainer:589 - Successfully waited for workers to finish.

可以看到消息监听容器关闭的日志,然后再传入开关参数为true,调用后会启动所有队列消息消费。

停止、启动指定队列消费

上面提到了RabbitListenerEndpointRegistry.getListenerContainers()可以获取到所有队列的消费监听容器列表,我们可以使用MessageListenerContainer中获取消费的队列名进行判断,以实现指定队列的停止、启动消费。

实现代码如下所示:

java 复制代码
@Resource
RabbitListenerEndpointRegistry rabbitListenerEndpointRegistry;

@RequestMapping(value = "/startStopConsumer")
@ApiOperation(value = "启动/暂停指定队列消息消费")
public Response startStopConsumer(@RequestParam(value = "queueName", required = false) String queueName,
									@RequestParam(value = "consumeSwitch", required = true) boolean consumeSwitch) {
	log.info("启动/暂停指定队列消息消费,consumeSwitch:{},queueName:{}",consumeSwitch,queueName);
	//获取所有消息监听容器
	Collection<MessageListenerContainer> listenerContainers = rabbitListenerEndpointRegistry.getListenerContainers();
	for (MessageListenerContainer container : listenerContainers) {
		SimpleMessageListenerContainer con = (SimpleMessageListenerContainer) container;
		//消息监听容器要消费的队列名称集合
		List<String> queueNamesList = Arrays.asList(con.getQueueNames());
		//判断容器中的队列名称是否包含需要调整的队列名参数
		if (queueNamesList.contains(queueName)) {
			if(consumeSwitch){
				con.start();
			}else{
				con.stop();
			}
		}
	}
	return Response.success();
}

传入开关参数为false,停止pay_work_notify队列消费者消费,调用后控制台看到如下日志

2023-09-04 19:51:37.130 +0800 [TID: N/A] [http-nio-8080-exec-1] INFO c.b.t.m.p.w.PayCashierMockController:80 - 启动/暂停指定队列消息消费,consumeSwitch:false,queueName:pay_work_notify

2023-09-04 19:51:37.200 +0800 [TID: N/A] [http-nio-8080-exec-1] INFO o.s.a.r.l.SimpleMessageListenerContainer:586 - Waiting for workers to finish.

2023-09-04 19:51:37.903 +0800 [TID: N/A] [http-nio-8080-exec-1] INFO o.s.a.r.l.SimpleMessageListenerContainer:589 - Successfully waited for workers to finish.

可以看到消息监听容器关闭的日志,然后再传入开关参数为true,调用后会启动pay_work_notify队列消息消费。

相关推荐
永远都不秃头的程序员(互关)28 分钟前
CANN赋能AIGC分布式训练:硬核通信,加速大模型智能生成新纪元
分布式·aigc
像少年啦飞驰点、35 分钟前
从零开始学 RabbitMQ:小白也能懂的消息队列实战指南
java·spring boot·微服务·消息队列·rabbitmq·异步编程
lekami_兰37 分钟前
RabbitMQ 延迟队列实现指南:两种方案手把手教你搞定
后端·rabbitmq·延迟队列
杜子不疼.2 小时前
CANN集合通信库HCCL的大规模分布式训练通信优化与拓扑感知实践
分布式
ALex_zry14 小时前
Redis Cluster 分布式缓存架构设计与实践
redis·分布式·缓存
为什么不问问神奇的海螺呢丶16 小时前
n9e categraf rabbitmq监控配置
分布式·rabbitmq·ruby
TTBIGDATA20 小时前
【Atlas】Atlas Hook 消费 Kafka 报错:GroupAuthorizationException
hadoop·分布式·kafka·ambari·hdp·linq·ranger
m0_687399841 天前
telnet localhost 15672 RabbitMQ “Connection refused“ 错误表示目标主机拒绝了连接请求。
分布式·rabbitmq
陌上丨1 天前
生产环境分布式锁的常见问题和解决方案有哪些?
分布式
新新学长搞科研1 天前
【智慧城市专题IEEE会议】第六届物联网与智慧城市国际学术会议(IoTSC 2026)
人工智能·分布式·科技·物联网·云计算·智慧城市·学术会议