spring boot 从0到1学习---07:spring boot整合RabbitMq之延时队列

生活不易,且行且学习吧

 

        前几天有同事手上有个老项目,效率比较低,压测的时候压死了,领导准备用mq分下流,但是这个项目接收到请求后又进行了二次转发,没法具体确定一条消息是否真正执行完成,能想到的是定时5S执行一条,这样能保证消息不丢失,还不会死掉。于是发现了mq的延时队列,在此记录下。

 

方式A,整体过期时间。

1,创建队列A,作为死信转发队列

/**
 * 注册队列A,死信转发队列,不处理消息,死信自动转发到B
 * @return
 */
@Bean
public Queue TestMqQueryA(){
	Map<String, Object> map = new HashMap<>();
	map.put("x-message-ttl", 10000);//设置10s过期时间
	//x-dead-letter-exchange参数是设置该队列的死信交换器(DLX),此处设置为B的Exchange
	map.put("x-dead-letter-exchange", MqContains.TestMqExchangeInB);
	//x-dead-letter-routing-key参数是给这个DLX指定路由键,此处设置为B的RoutingKey
	map.put("x-dead-letter-routing-key", MqContains.TestInBRouting);
	return new Queue(MqContains.TestMqQueryInA,true,false,false,map);
}

2,controller进行数据写入队列A

@RequestMapping(value="/sendMsgInA", method = RequestMethod.POST)
@ApiOperation(value="发送mq消息到A", notes="发送mq消息到A")
@ResponseBody
public String sendMsgInA(@RequestBody Map params) {
	String id = UUID.randomUUID().toString().replace("-","");
	String msgBody = "发送一条死信测试消息A,数据01,将在10秒后到达B";

	Map msgMap = new HashMap();
	msgMap.put("msgId",id);
	msgMap.put("msgBody",msgBody);

	//将消息携带绑定键值:TestInARouting 发送到交换机TestMqExchangeInA
	rabbitTemplate.convertAndSend(MqContains.TestMqExchangeInA,MqContains.TestInARouting,msgMap);

	logger.info("mqA消息发送成功");
	return "发送成功";
}

3,编写死信队列B的监听

@RabbitListener(queues = MqContains.TestMqQueryInB)
@RabbitHandler
public void process(Map testMessage) {
	logger.info("DirectReceiver消费者收到消息  : " + testMessage.toString());
}

4,测试,10秒后B正确收到消息并处理掉。

但此种方式无法适用高并发的情况,一次2000条数据进入A,会同时在10秒后全部进入队列B中,B会一次性消费2000条,依旧不适用。

 

方式B,单条消息过期时间。

1,配置死信转发队列A,取消过期时间

/**
 * 注册队列A,死信转发队列,不处理消息,死信自动转发到B
 * @return
 */
@Bean
public Queue TestMqQueryA(){
	Map<String, Object> map = new HashMap<>();
//        map.put("x-message-ttl", 10000);//设置10s过期时间
	//x-dead-letter-exchange参数是设置该队列的死信交换器(DLX),此处设置为B的Exchange
	map.put("x-dead-letter-exchange", MqContains.TestMqExchangeInB);
	//x-dead-letter-routing-key参数是给这个DLX指定路由键,此处设置为B的RoutingKey
	map.put("x-dead-letter-routing-key", MqContains.TestInBRouting);
	return new Queue(MqContains.TestMqQueryInA,true,false,false,map);
}

2,写入数据A的方法调整,增加每条消息的过期时间

@RequestMapping(value="/sendMsgInA", method = RequestMethod.POST)
@ApiOperation(value="发送mq消息到A", notes="发送mq消息到A")
@ResponseBody
public String sendMsgInA(@RequestBody Map params) {
	String id = UUID.randomUUID().toString().replace("-","");


	for(int i=1;i<11;i++) {

		String msgBody = "发送一条死信测试消息A"+i+",数据0"+i+",将在"+(10*i)+"秒后到达B";

		int finalI = i;
		MessagePostProcessor processor = message -> {
			MessageProperties messageProperties = message.getMessageProperties();

			//设置编码格式
			messageProperties.setContentEncoding("UTF-8");
			//设置过期时间10*1000
			messageProperties.setExpiration(String.valueOf(10000* finalI));
			return message;
		};

		Map msgMap = new HashMap();
		msgMap.put("msgId", "id:0"+i);
		msgMap.put("msgBody", msgBody);
		//将消息携带绑定键值:TestInARouting 发送到交换机TestMqExchangeInA
		rabbitTemplate.convertAndSend(MqContains.TestMqExchangeInA,MqContains.TestInARouting,msgMap,processor);
		logger.info("mqA"+i+"消息发送成功");
	}
	return "发送成功";
}

3,查看日志,依次10秒消费一个

应用此方法,满足领导要求。。。。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值