rabbitmq之SimpleMessageListenerContainer监听容器

最近做了一个利用rabbitmq作为延迟队列给微信推送模板消息的业务

具体场景就是通过定时任务每天凌晨一点查到redis的记录,然后发送给mq,定时到指定时间消费,有个问题就是可能会有一天点击推送模板消息的用户会有很多,会存在消费者消费不过来的场景,了解到SimpleMessageListenerContainer这个容器,可以帮我动态新增消费者。

  1. 先定义在rabbitmqconfig的配置类中定义一个容器,容器指定监听监听的队列以及消费者的数量,可以根据自己的消息数量定义初始数量和最大消费者数量
	@Bean
	public SimpleMessageListenerContainer signinMessageContainer(ConnectionFactory connectionFactory) {
		SimpleMessageListenerContainer container = new SimpleMessageListenerContainer(connectionFactory);
		container.setQueues(templateMsgQueue());    // 监听的队列
		container.setConcurrentConsumers(concurrentConsumers);    // 当前的消费者数量
		container.setMaxConcurrentConsumers(maxConcurrentConsumers); // 最大的消费者数量
		container.setDefaultRequeueRejected(true); // 是否重回队列
		container.setAcknowledgeMode(AcknowledgeMode.MANUAL); // 签收模式
		container.setExposeListenerChannel(true);
		container.setConsumerTagStrategy(new ConsumerTagStrategy() {    // 消费端的标签策略
			@Override
			public String createConsumerTag(String queue) { //为每个动态的消费者定义一个tag
				return queue + "_" + UUID.randomUUID().toString();
			}
		});
		
		container.setMessageListener(new MqConsumerHandle()); //设置监听类
		return container;
	}

在这里插入图片描述

可以看到我的定义的初始消费者的3个,当你的消息堵塞太多的时候,它会帮我自动扩展到我的最大消费者数量,是不是很方便
  1. 这里因为只能指定一个消费者类,所以我做了一个消息处理类,这个处理类里面再去处理消息,分发到具体的消费类,处理类需要实现ChannelAwareMessageListener,因为这个接口有channel,可以自己去选择签收到消息,我这里是自己封装了一下消息体,里面有一个具体转发的类名,这样一个处理类就可以处理很多的类
@Component
public class MqConsumerHandle implements ChannelAwareMessageListener{
	
	@Override
	public void onMessage(Message message,Channel channel) {
		
		try {
			//解析消息体
			MqMessageVo messageVo=JSON.parseObject(message.getBody(),MqMessageVo.class);
			
			//调用具体实现类
			BaseConsumer baseConsumer=(BaseConsumer) SpringUtils.getBean(messageVo.getClassName());
			baseConsumer.OnMessage(messageVo.getMessage());
			
			channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
		} catch (Exception e) {
			System.out.println("mq消息转发具体实现异常"+e);
			try {
				channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, true);
			} catch (IOException e1) {
				e1.printStackTrace();
			}
		}	
	}	
}
  1. 顺便提一下遇到的一个问题,在处理类处理消息的时候看到Message的body字段是byte数组的,但是我的生产者又是发送的json消息,发现又要转换一下,后面查了一下发现是可以设置消息的content-type的,你设置的什么,它就会转成什么类型。设置成json格式以后,message的boye就会帮我们转成json,原来默认就是byte的
	public void sendTemplateMsgDelayMsg(String msg, Integer delayTime) {
		try {
			
			//构建消息,设置content-type为json格式
			Message message=MessageBuilder.withBody(msg.getBytes()).setContentType(MessageProperties.CONTENT_TYPE_JSON).build();
			
			//发送延迟消息
			rabbitTemplate.convertAndSend(MQEnum.DELAYED_TEMPLATEMSG_EXCHANGE_NAME, MQEnum.DELAYED_TEMPLATEMSG_ROUTING_KEY, message, a -> {
				a.getMessageProperties().setDelay(delayTime);
				return a;
			});
		} catch (Exception e) {
			System.out.println("发送消息异常");
		}

	}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值