RabbitMQ高级-死信队列

概述

DLX,全称为Dead-Letter-Exchange , 可以称之为死信交换机,也有人称之为死信邮箱。当消息在一个队列中变成死信(dead message)之后,它能被重新发送到另一个交换机中,这个交换机就是DLX ,绑定DLX的队列就称之为死信队列。
消息变成死信,可能是由于以下的原因:

  • 消息被拒绝
  • 消息过期
  • 队列达到最大长度

DLX也是一个正常的交换机,和一般的交换机没有区别,它能在任何的队列上被指定,实际上就是设置某一个队列的属性。当这个队列中存在死信时,Rabbitmq就会自动地将这个消息重新发布到设置的DLX上去,进而被路由到另一个队列,即死信队列。
要想使用死信队列,只需要在定义队列的时候设置队列参数 x-dead-letter-exchange 指定交换机即可。

RabbitMQ高级-死信队列_第1张图片
RabbitMQ高级-死信队列_第2张图片

1、消息过期进入死信队列

1、创建交换机和队列,并且绑定

package com.sky.config;

import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.HashMap;
import java.util.Map;

/**
 * @author 尹稳健~
 * @version 1.0
 */
@Configuration
public class TTLDirectRabbitMQConfig {

    // 声明注册交换机
    @Bean
    public DirectExchange ttlDirectExchange(){
        return new DirectExchange("ttl_direct_exchange");
    }

    // 声明队列
    @Bean
    public Queue ttlQueueDirect(){
        Map<String,Object> args = new HashMap<>();
        // 设置过期时间
        args.put("x-message-ttl",5000);
        // 设置死信队列
        args.put("x-dead-letter-exchange","dead_direct_exchange");
        // 设置 路由key
        args.put("x-dead-letter-routing-key","dead");
        return new Queue("ttl.direct.queue",true,false,false,args);
    }

    // 交换机和队列绑定
    @Bean
    public Binding ttlBindingDirect(){
        return BindingBuilder.bind(ttlQueueDirect()).to(ttlDirectExchange()).with("ttl");
    }
}

2、发送消息

public void makeOrderTTL(String userId, String productId, int num) {
    // 1:根据商品id查询库存是否充足

    //2:保存订单
    String orderId = UUID.randomUUID().toString();
    System.out.println("订单生成成功"+orderId);
    String exchangeName = "ttl_direct_exchange";
    String routeKey = "ttl";
    rabbitTemplate.convertAndSend(exchangeName,routeKey,orderId);

}

3、测试

刚刚发送消息时:
RabbitMQ高级-死信队列_第3张图片

消息过期后:
RabbitMQ高级-死信队列_第4张图片

小结

消息过期后转入死信交换机,然后通过死信交换机发送到死信队列中,其实死信交换机和其他的交换机没啥区别,也只是一个普普通通的交换机,不要把它想得很复杂,他只是一个回收站罢了。

  • x-dead-letter-exchange 设置死信交换机
  • x-dead-letter-routing-key 设置死信队列路由key
  • x-message-ttl 设置过期时间

2、消息队列达到最大数,其他的信息进入死信队列

1、创建交换机和队列,绑定

package com.sky.config;

import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.DirectExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.HashMap;
import java.util.Map;

/**
 * @author 尹稳健~
 * @version 1.0
 */
@Configuration
public class TTLDirectRabbitMQConfig {

    // 声明注册交换机
    @Bean
    public DirectExchange ttlDirectExchange(){
        return new DirectExchange("ttl_direct_exchange");
    }
    
    // 声明队列
    @Bean
    public Queue maxQueueDirect(){
        Map<String,Object> args = new HashMap<>();
        // 设置过期时间
        //args.put("x-message-ttl",5000);
        // 设置队列最大数
        args.put("x-max-length",3);
        // 设置死信队列
        args.put("x-dead-letter-exchange","dead_direct_exchange");
        // 设置 路由key
        args.put("x-dead-letter-routing-key","dead");
        return new Queue("max.direct.queue",true,false,false,args);
    }

    // 交换机和队列绑定
    @Bean
    public Binding maxBindingDirect(){
        return BindingBuilder.bind(maxQueueDirect()).to(ttlDirectExchange()).with("max");
    }
}

2、发送消息

public void makeOrderMax(String userId, String productId, int num) {
    // 1:根据商品id查询库存是否充足
    //2:保存订单
    String orderId = UUID.randomUUID().toString();
    System.out.println("订单生成成功"+orderId);
    String exchangeName = "ttl_direct_exchange";
    String routeKey = "max";
    rabbitTemplate.convertAndSend(exchangeName,routeKey,orderId);

}

3、测试

因为队列最大消息数设置为3条,我们测试一下队列达到最大数时,哪些消息会进入到死信队列中。

在这里插入图片描述

在这里插入图片描述

小结

通过多次发送消息发现:当队列达到最大数时,继续发送消息,先前发送的消息会被丢弃到队列中,这就很像数据结构中的队列了,先进先出。

你可能感兴趣的:(RabbitMQ,SpringBoot,rabbitmq,java,分布式)