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 


	org.springframework.boot
	spring-boot-starter-amqp

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,原码解释:

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

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

    /**
     * 延时队列交换机
     *
     * @return
     */
	@Bean
	public CustomExchange delayExchange() {
		Map 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
springboot rabbitMQ 纯注解版 DLX 死信队列以插件形式实现消息延迟处理_第2张图片

Queues,注意插件版的死信队列Features字段不会显示DLXspringboot rabbitMQ 纯注解版 DLX 死信队列以插件形式实现消息延迟处理_第3张图片

4.测试:

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

控制台打印:

springboot rabbitMQ 纯注解版 DLX 死信队列以插件形式实现消息延迟处理_第4张图片 成功!

 

 

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

你可能感兴趣的:(springboot rabbitMQ 纯注解版 DLX 死信队列以插件形式实现消息延迟处理)