springboot rabbitMQ 纯注解版 DLX 死信队列以插件形式实现消息延迟处理

1.业务应用场景

在项目实战中我们可能会遇到:

  1. 商城订单要求在未支付状态下30分钟后自动取消;
  2. 商品发货后15天自动收货、评价等等...
  3. 以及各种操作后要求多长时间才执行另外一个操作的业务。

一般我们会想到的解决方法是利用定时任务定时查询数据库再进行相关操作,当数据量大的时候,定时任务的反复执行就会非常消耗内存,那么这个时候我们可以使用MQ消息队列中的延时消息处理来实现类似这种的业务操作。

2.特性

RabbitMQ在设计之初本身不支持延时队列功能,但是我们可以通过TTL(Time To Live)来控制消息的生存时间结合DLX(Dead Letter Exchanges)死信队列达到消息的延迟处理。

3.实战(插件版)

1.rabbitMQ官网下载rabbitmq-delayed-message-exchange插件(为了不必要的麻烦一定要下载跟个人安装的rabbit版本一致)

放到服务器rabbitMQ安装包下的plugins目录中,并执行以下命令来安装插件:

rabbitmq-plugins enable rabbitmq-delayed-message-exchange

2.pom引用spring-boot-starter-amqp 

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>

3.添加yml配置

spring: 
  rabbitmq: 
    host: 127.0.0.1
    port: 5672
    username: guest
    password: guest
    virtual-host: /

创建MqReceiver接收消息类,使用@RabbitListener注解监听消息并同时绑定queue队列、exchange交换机、routing key

@Component
public class MqReceiver {
	/**
	 * rabbitmq_delayed_message_exchange插件版延时队列
	 * @param msg
	 * @param message
	 * @param channel
	 */
	@RabbitListener(bindings= @QueueBinding(value = @Queue(value = MQConstants.DELAY_QUEUE, durable = "true"),
			exchange = @Exchange(value = MQConstants.DELAY_EXCHANGE,type=ExchangeTypes.DIRECT,
			arguments=@Argument(name="x-delayed-type",value="direct"),delayed=Exchange.TRUE),
			key = MQConstants.DELAY_KEY))
	public void receiveDelay(String msg,Message message,Channel channel) {
		System.out.println(message.toString());
		System.out.println(message.getMessageProperties().getReceivedDelay());
		System.out.println("-----------收到消息:"+msg+",当前时间:"+new Date());
	}

}

注意:delayed = true 就是说明使用rabbitmq-delayed-message-exchange,原码解释:

众所周知@注解的使用极为方便,并且极大的减少的了代码量,那么对于初次使用者可能不是很明白整个QueueBinding 的流程,可以结合下面代码理解(仅作参考理解):

    /**
     * 延时队列交换机
     *
     * @return
     */
	@Bean
	public CustomExchange delayExchange() {
		Map<String, Object> args = new HashMap<>();
		args.put("x-delayed-type", "direct");
		return new CustomExchange(DELAY_EXCHANGE, "x-delayed-message", true, false,args);
	}
	
	/**
	 * 定义延时队列
	 *
	 */
	@Bean
	public Queue delayQueue() {
		return new Queue(DELAY_QUEUE, true);
	}
	
	/**
       * 给延时队列绑定交换机
       *
       * @return
       */
	@Bean
	public Binding binding() {
		return BindingBuilder.bind(delayQueue()).to(delayExchange()).with(DELAY_KEY).noargs();
	}

 

 MQConstants类:

    /**
	 * 延迟队列
	 */
	public final static String DELAY_QUEUE = "delay.queue";
	
	/**
	 * 交换机名称
	 */
	public final static String DELAY_EXCHANGE = "delay.exchange";
	
	/**
	 * routingKey
	 */
	public final static String DELAY_KEY = "delay.key";

发送消息:

@RestController
public class TestContoller {

	@Autowired
	private AmqpTemplate amqpTemplate;
	
	@GetMapping(value = "/send/{exp}")
	public String test(@PathVariable("exp") Integer exp) {
		String msg = "发送时间:"+new Date();
		amqpTemplate.convertAndSend(MQConstants.DELAY_EXCHANGE,MQConstants.THEATRE_DELAY_KEY,msg,message -> {
			message.getMessageProperties().setDelay(exp);// 单位 毫秒
			return message;
			});
		return "---------sendTime:"+new Date();
	}
}

 然后启动项目,可以看到rabbitMQ控制台显示出了定义的exchange,注意type显示为x-delayed-message

Queues,注意插件版的死信队列Features字段不会显示DLX

4.测试:

调用接口,定义10秒的延迟

控制台打印:

 成功!

 

 

----我是francis, 谨以此记录自己精彩的程序人生。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值