一、死信概述

死信队列产生的背景

  • RabbitMQ死信队列俗称,备胎队列;消息中间件因为某种原因拒收该消息后,可以转移到死信队列中存放,死信队列也可以有交换机和路由key等。

产生死信队列的原因 (前提是设置了死信队列)

  1. 消息投递到MQ中存放 消息已经过期  消费者没有及时消费服务器中的消息过期之后,会转移到备胎死信队列存放   /   (我们可以根据这个特性去实现例如订单回滚等业务场景)

  2. 队列达到最大的长度 (队列容器已经满了)

  3. 消费者消费多次消息失败,就会转移存放到死信队列

死信队列的架构原理

  • 信队列和普通队列区别不是很大

  • 普通与死信队列都有自己独立的交换机和路由key、队列和消费者。

 

二、实现简单demo

· application.yml

spring:
  rabbitmq:
    host: 127.0.0.1
    port: 5672
    username: guest
    password: guest
    virtual-host: /MuPing
#自定义内容
sdkj:
  #通常
  usual:
    exchange_name: usual_exchange
    queue_name: usual_queue
    #路由key
    routingKey: sdkj_usual
  #死信
  dead:
    exchange_name: dead_exchange
    queue_name: dead_queue
    #路由key
    routingKey: sdkj_dead

 

1.SiXinConfig

  1 package com.sdkj.config;
  2 
  3 import org.springframework.amqp.core.Binding;
  4 import org.springframework.amqp.core.BindingBuilder;
  5 import org.springframework.amqp.core.DirectExchange;
  6 import org.springframework.amqp.core.Queue;
  7 import org.springframework.beans.factory.annotation.Value;
  8 import org.springframework.context.annotation.Bean;
  9 import org.springframework.stereotype.Component;
 10 
 11 import java.util.HashMap;
 12 import java.util.Map;
 13 
 14 /**
 15  * @Author wangshuo
 16  * @Date 2022/5/7, 21:34
 17  * Please add a comment
 18  */
 19 @Component
 20 public class SiXinConfig {
 21 
 22     @Value("${sdkj.usual.exchange_name}")
 23     private String orderExchange;
 24 
 25     @Value("${sdkj.usual.queue_name}")
 26     private String orderQueue;
 27 
 28     /**
 29      * 订单路由key
 30      */
 31     @Value("${sdkj.usual.routingKey}")
 32     private String orderRoutingKey;
 33     /**
 34      * 死信交换机
 35      */
 36     @Value("${sdkj.dead.exchange_name}")
 37     private String dlxExchange;
 38 
 39     /**
 40      * 死信队列
 41      */
 42     @Value("${sdkj.dead.queue_name}")
 43     private String dlxQueue;
 44     /**
 45      * 死信路由
 46      */
 47     @Value("${sdkj.dead.routingKey}")
 48     private String dlxRoutingKey;
 49 
 50     /**
 51      * 声明死信交换机
 52      *
 53      * @return DirectExchange
 54      */
 55     @Bean
 56     public DirectExchange dlxExchange() {
 57         return new DirectExchange(dlxExchange);
 58     }
 59 
 60     /**
 61      * 声明死信队列
 62      *
 63      * @return Queue
 64      */
 65     @Bean
 66     public Queue dlxQueue() {
 67         return new Queue(dlxQueue);
 68     }
 69 
 70     /**
 71      * 声明订单业务交换机
 72      *
 73      * @return DirectExchange
 74      */
 75     @Bean
 76     public DirectExchange orderExchange() {
 77         return new DirectExchange(orderExchange);
 78     }
 79 
 80     /**
 81      * 声明订单队列
 82      *
 83      * @return Queue
 84      */
 85     @Bean
 86     public Queue orderQueue() {
 87         // 订单队列绑定我们的死信交换机
 88         Map<String, Object> arguments = new HashMap<>(2);
 89         arguments.put("x-dead-letter-exchange", dlxExchange);
 90         arguments.put("x-dead-letter-routing-key", dlxRoutingKey);
 91         return new Queue(orderQueue, true, false, false, arguments);
 92     }
 93 
 94     /**
 95      * 绑定死信队列到死信交换机
 96      *
 97      * @return Binding
 98      */
 99     @Bean
100     public Binding binding() {
101         return BindingBuilder.bind(dlxQueue())
102                 .to(dlxExchange())
103                 .with(dlxRoutingKey);
104     }
105 
106 
107     /**
108      * 绑定订单队列到订单交换机
109      *
110      * @return Binding
111      */
112     @Bean
113     public Binding orderBinding() {
114         return BindingBuilder.bind(orderQueue())
115                 .to(orderExchange())
116                 .with(orderRoutingKey);
117     }
118 }

2.OrderProducer

 1 package com.sdkj.producer;
 2 
 3 import org.springframework.amqp.rabbit.core.RabbitTemplate;
 4 import org.springframework.beans.factory.annotation.Autowired;
 5 import org.springframework.beans.factory.annotation.Value;
 6 import org.springframework.web.bind.annotation.RequestMapping;
 7 import org.springframework.web.bind.annotation.RestController;
 8 
 9 /**
10  * @Author wangshuo
11  * @Date 2022/5/7, 21:46
12  * Please add a comment
13  */
14 @RestController
15 public class OrderProducer {
16 
17     @Autowired
18     private RabbitTemplate rabbitTemplate;
19     /**
20      * 订单交换机
21      */
22     @Value("${sdkj.usual.exchange_name}")
23     private String orderExchange;
24     /**
25      * 订单路由key
26      */
27     @Value("${sdkj.usual.routingKey}")
28     private String orderRoutingKey;
29 
30     @RequestMapping("/sendOrder")
31     public String sendOrder() {
32         String msg = "哈哈哈";
33         rabbitTemplate.convertAndSend(orderExchange, orderRoutingKey, msg, message -> {
34             // 设置消息过期时间 10秒过期
35             message.getMessageProperties().setExpiration("10000");
36             return message;
37         });
38         return "success";
39     }
40 }

3.UsualConsumer

 1 package com.sdkj.consumer;
 2 
 3 import org.springframework.amqp.rabbit.annotation.RabbitListener;
 4 import org.springframework.stereotype.Component;
 5 
 6 /**
 7  * @Author wangshuo
 8  * @Date 2022/5/7, 21:44
 9  * Please add a comment
10  */
11 @Component
12 public class UsualConsumer {
13 
14     /*
15         监听回调方法
16      */
17     @RabbitListener(queues = "usual_queue")
18     public void orderConsumer(String msg) {
19         System.out.println("正常订单消费者消息MSG: " + msg);
20     }
21 }

4.DeadConsumer

 1 package com.sdkj.consumer;
 2 
 3 import org.springframework.amqp.rabbit.annotation.RabbitListener;
 4 import org.springframework.stereotype.Component;
 5 
 6 /**
 7  * @Author wangshuo
 8  * @Date 2022/5/7, 21:44
 9  * Please add a comment
10  */
11 @Component
12 public class DeadConsumer {
13 
14     /**
15      * 死信队列监听队列回调的方法
16      *
17      * @param msg
18      */
19     @RabbitListener(queues = "dead_queue")
20     public void orderConsumer(String msg) {
21         System.out.println("死信队列消费订单消息: " + msg);
22     }
23 }