Bootstrap

SpringBoot实现RabbitMQ延迟队列

一、介绍

RabbitMQ 延迟消息队列是一种可以把消息存储在队列中,但是只有在达到特定的等待时间之后才能被消费的机制。这种机制可以用于处理各种需要延迟处理的任务,例如发送邮件、推送消息等。

二、安装延迟队列

1.首先要在Docker中安装RabbitMQ

Docker安装RabbitMq(rabbitmq:3.9.13)_docker 安装rabbitmq-CSDN博客文章浏览阅读708次,点赞12次,收藏5次。用户名 : guest 密码: guest。注:如果为本地虚拟机安装就不需要执行。_docker 安装rabbitmqhttps://blog.csdn.net/cmh1008611/article/details/141950134?fromshare=blogdetail&sharetype=blogdetail&sharerId=141950134&sharerefer=PC&sharesource=cmh1008611&sharefrom=from_link

2.官网下载插件

https://www.rabbitmq.com/community-pluginsicon-default.png?t=O83Ahttps://www.rabbitmq.com/community-plugins

(1)选择延迟消息插件

(2)根据版本进行选择

注:RabbitMQ是什么版本的,下载的插件就得是什么版本的,得对应上

我的RabbitMQ版本为3.9.13所以下载3.9.0的插件

(3)下载完成

(4)将下载完成的文件上传到服务器

(5)进入RabbitMQ容器

docker exec -it rabbitmq /bin/bash

(6)启用插件

rabbitmq-plugins enable rabbitmq_delayed_message_exchange

(7)退出容器

exit

 

三、SpringBoot代码实现

1.导入RabbitMQ依赖

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

 

2.添加相关配置

我这是最基础的配置

spring:
  rabbitmq:
    host:  #ip
    port: 5672
    username: guest
    password: guest

3.配置延迟队列

/**
 * 延迟队列
 */
@Configuration
public class DelayedQueueConfig {
    /**
     * 队列
     */
    public static final String DELAYED_QUEUE_NAME = "delayed_queue";
    /**
     * 交换机
     */
    public static final String DELAYED_EXCHANGE_NAME = "DELAYED_EXCHANGE";
    /**
     * 交换机类型
     */
    public static final String DELAYED_EXCHANGE_TYPE = "x-delayed-message";
    /**
     * 交换机路由键
     */
    public static final String DELAYED_ROUTING_KEY = "delayed";

    /**
     * 声明延迟队列
     */
    @Bean
    public Queue delayedQueue() {
        return new Queue(DELAYED_QUEUE_NAME);
    }

    /**
     * 声明延迟队列交换机
     */
    @Bean
    public CustomExchange delayedExchange() {
        Map<String, Object> map = new HashMap<>();
        map.put("x-delayed-type", "direct");
        /**
         * 生命自定义交换机
         * 第一个参数: 交换机名称
         * 第二个参数: 交换机类型
         * 第三个参数: 是否需要持久化
         * 第四个参数: 是否自动删除
         * 第五个参数: 其他参数
         */
        return new CustomExchange(DELAYED_EXCHANGE_NAME, DELAYED_EXCHANGE_TYPE, true, false, map);
    }

    /**
     * 绑定队列和延迟交换机
     */
    @Bean
    public Binding delayedQueueBindingDelayedExchange(
            @Qualifier("delayedQueue") Queue delayedQueue,
            @Qualifier("delayedExchange") Exchange delayedExchange
    ) {
        return BindingBuilder.bind(delayedQueue).to(delayedExchange).with(DELAYED_ROUTING_KEY).noargs();
    }
}

相关解释

路由键的作用

DELSEY_ROUTING_KEY 就是你在发送消息时指定的 路由键,它决定了消息应该进入哪个队列。

交换机与队列的绑定

delayedQueue 队列与 delayedExchange 交换机通过指定的路由键("delayed")绑定在一起。换句话说,任何发送到 delayedExchange 交换机,并且路由键为 "delayed" 的消息都会进入 delayedQueue 队列。

运行项目之后的效果(交换机和延迟队列通过路由键进行关联)

 4.生产者

rabbitTemplate.convertAndSend(DelayedQueueConfig.DELAYED_EXCHANGE_NAME, DelayedQueueConfig.DELAYED_ROUTING_KEY, 1234, correlationData -> {
    correlationData.getMessageProperties().setDelay(10000);
    return correlationData;
});
参数解释
(1)DelayedQueueConfig.DELAYED_EXCHANGE_NAME

这是发送消息的交换机(Exchange)名称。在RabbitMQ中,交换机用于将消息路由到一个或多个队列。这个参数指定了要将消息发送到哪个交换机。DELAYED_EXCHANGE_NAME 是一个常量,可能会在配置类 DelayedQueueConfig 中定义。

  • 类型: String
  • 作用: 指定目标交换机的名称。
(2)DelayedQueueConfig.DELAYED_ROUTING_KEY

这是消息的路由键(Routing Key)。在RabbitMQ中,路由键用于决定消息路由到哪个队列。DELAYED_ROUTING_KEY 是一个常量,表示发送消息时使用的路由键。路由键的选择通常取决于交换机类型,某些交换机(如Direct或Topic交换机)会根据路由键的值来决定消息的投递目标。

  • 类型: String
  • 作用: 指定消息的路由键,决定消息的目标队列。
(3)1234

这是发送的消息内容。在这个例子中,消息的内容是一个整数(1234),可以是任何类型的对象。RabbitMQ会将这个消息对象序列化为字节流,并将其发送到指定的交换机。

  • 类型: Object(此例为 Integer)
  • 作用: 发送到RabbitMQ的消息体。可以是任何类型的数据,RabbitMQ会将其序列化。
(4)correlationData -> { correlationData.getMessageProperties().setDelay(10000); return correlationData; }

这是一个回调函数,用于在发送消息之前修改消息的属性。它接收一个 correlationData 对象,该对象包含消息的相关信息。你可以通过这个回调来修改消息的属性,例如设置消息的延迟时间。

  • 类型: MessagePostProcessor(这是一个函数式接口,允许你在消息发送前对其进行处理)
  • 作用: 在消息发送前修改消息的属性。在这里,回调函数通过 correlationData.getMessageProperties().setDelay(10000) 设置消息延迟时间为10秒(10000毫秒)。这意味着消息将在10秒后才会投递到目标队列。

 

 5.消费者

import com.rabbitmq.client.Channel;
import com.shopgoods.order.config.DelayedQueueConfig;
import lombok.extern.log4j.Log4j2;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * 延迟队列消费者
 */
@Log4j2
@Component
public class OrderVoluntarily {
    @RabbitListener(queues = DelayedQueueConfig.DELAYED_QUEUE_NAME)
    public void receiveDelayQueue(Integer a, Message message, Channel channel) throws IOException {
        log.info("当前时间:{},取出的值为{}", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()),a);
    }
}

6.效果

;