RabbitMQ的死信队列和延迟队列

RabbitMQ的死信队列和延迟队列

死信队列

什么是死信队列

简单来说,就是普通队列中的消息符合某个条件时,会交由另一个交换机转移到另一个队列,这个队列就是死信队列,负责转移的交换机就是死信交换机。

什么条件才会转移到死信队列呢

  • 队列消息长度到达限制
  • 消费者拒接消费信息
  • 消息超时未被消费,分为两种,一种是消息自身设置的超时时间,另一种则是队列的超时时间。

怎么配置死信队列

java 复制代码
package com.xiaow.fileserver.config;

import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitAdmin;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class RabbitMQConfig {

    @Bean
    public Queue normQueue() {
        return QueueBuilder.durable("normal_queue")
//              设置死信交换机
                .deadLetterExchange("DeadExchange")
//              设置死信队列路由键
                .deadLetterRoutingKey("timeout_routing")
                .build();
    }


    //  正常交换机
    @Bean
    DirectExchange normalExchange() {
        //  return new DirectExchange("TestDirectExchange",true,true);
        return new DirectExchange("NormalExchange", true, false);
    }


    //绑定常规队列
    @Bean
    Binding bindingNormal() {
        return BindingBuilder.bind(normQueue()).to(normalExchange()).with("normal_routing");
    }


    //  死信队列
    @Bean
    public Queue dQueue() {
        return QueueBuilder.durable("d_queue")
                .build();
    }

    //  死信交换机
    @Bean
    DirectExchange DeadExchange() {
        //  return new DirectExchange("TestDirectExchange",true,true);
        return new DirectExchange("DeadExchange", true, false);
    }


    //  死信队列与死信交换机绑定
    @Bean
    Binding bindingD() {
        return BindingBuilder.bind(dQueue()).to(DeadExchange()).with("timeout_routing");
    }

}

死信队列有什么用呢?

以淘宝下订单为例,用户下订单时我们可以发送一个消息到队列中,并设置超时时间,当超过了超时时间用户仍未付款,则删除该订单。

模拟一下,这里我们写一下发送消息的接口和接收消息的Recevier

发送消息的接口

java 复制代码
 @GetMapping("testmq")
    public Result testmq(){
        String orderId = String.valueOf(UUID.randomUUID());
        String messageData = "下订单!";
        String createTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        Map<String,Object> map=new HashMap<>();
        map.put("orderId",orderId);
        map.put("messageData",messageData);
        map.put("createTime",createTime);
        rabbitTemplate.convertAndSend("NormalExchange", "normal_routing", map,message -> {
            MessageProperties messageProperties = message.getMessageProperties();
            // 设置过期时间
            messageProperties.setExpiration("5000");
            return message;
        });
        return Result.succ("ok");
    }

接收消息的Recevier

java 复制代码
@Component
@RabbitListener(queues = "d_queue")
public class DReceiver {

    @RabbitHandler
    public void process(Map testMessage) {
        System.out.println("订单号:" + testMessage.get("orderId") + ", 未付款,自动取消订单");
    }

}

然后你就可以看到

延迟队列

什么是延迟队列呢

顾名思义,也就是说消息到了队列之后不会立刻被处理,会等到指定时间之后才进行处理。

是不是有点眼熟?

咱们刚才利用死信队列做的事不就是这样吗!

当消息到达5秒之后,才进行删除订单操作。

死信队列结合过期时间也就实现了延迟队列。

惰性队列

什么是惰性队列

遇到消息堆积问题,会导致内存占用过大,因此有了惰性队列。

  • 接收到消息后直接存入磁盘而非内存
  • 消费者要消费消息时才会从磁盘中读取并加载到内存
  • 支持数百万条的消息存储

怎么设置

java 复制代码
  @Bean
    public Queue lazyQueue() {
        return QueueBuilder.durable("lazyQueue")
                .lazy()
                .build();
    }

有什么优点/缺点

存储到磁盘,第一个优点就是信息存储量更大了。但磁盘和内存之间的速度差异导致其效率有所降低。

总结

简单记录一下,欢迎大家指正。

相关推荐
丘山子33 分钟前
一些鲜为人知的 IP 地址怪异写法
前端·后端·tcp/ip
CopyLower1 小时前
在 Spring Boot 中实现 WebSockets
spring boot·后端·iphone
.生产的驴2 小时前
SpringBoot 封装统一API返回格式对象 标准化开发 请求封装 统一格式处理
java·数据库·spring boot·后端·spring·eclipse·maven
景天科技苑2 小时前
【Rust】Rust中的枚举与模式匹配,原理解析与应用实战
开发语言·后端·rust·match·enum·枚举与模式匹配·rust枚举与模式匹配
追逐时光者3 小时前
MongoDB从入门到实战之Docker快速安装MongoDB
后端·mongodb
大新新大浩浩3 小时前
arm64适配系列文章-第六章-arm64环境上rabbitmq-management的部署,构建cluster-operator
rabbitmq·arm
方圆想当图灵3 小时前
深入理解 AOP:使用 AspectJ 实现对 Maven 依赖中 Jar 包类的织入
后端·maven
豌豆花下猫3 小时前
Python 潮流周刊#99:如何在生产环境中运行 Python?(摘要)
后端·python·ai
嘻嘻嘻嘻嘻嘻ys3 小时前
《Spring Boot 3 + Java 17:响应式云原生架构深度实践与范式革新》
前端·后端
异常君3 小时前
线程池隐患解析:为何阿里巴巴拒绝 Executors
java·后端·代码规范