spring boot rabbitMQ延时队列 实现

本文介绍如何在Spring Boot项目中集成RabbitMQ,并通过示例代码演示如何配置延时队列,包括发送和接收消息的过程。

spring boot 使用rabbitMQ
需要导入相关的相关依赖如下:

 

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

AMQP默认实现为rabbitMQ。

 

为了定制化的配置放弃了boot的自动配置,So,以下为RabbitMQ的配置文件:

 

package com.fengbaogu.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.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * rabbitmq 的配置类
 * @author LiaoLe
 */
@Configuration
public class RabbitMQConfig {
    /** 消息交换机的名字*/
    public static final String EXCHANGE = "delayed_exchange";
    /** 队列key1*/
    public static final String ROUTING = "notify";
    /** 队列名*/
    public static final String QUEUE = "delayed_queue";
    /** rabbit MQ 账号*/
    public static final String USERNAME = "liaoke";
    /**rabbit MQ 密码*/
    public static final String PASSWORD = "198461lk";
    /**rabbit MQ 地址*/
    public static final String RABBITMQ_ADDRESS="localhost";
    /**rabbit MQ 端口*/
    public static final Integer RABBITMQ_PORT=5672;

    /**
     * 配置链接
     * @return
     */
    @Bean
    public ConnectionFactory connectionFactory() {
        CachingConnectionFactory connectionFactory = new CachingConnectionFactory(RABBITMQ_ADDRESS,RABBITMQ_PORT);
        connectionFactory.setUsername(USERNAME);
        connectionFactory.setPassword(PASSWORD);
        connectionFactory.setVirtualHost("/");
        connectionFactory.setPublisherConfirms(true); /**需要设置 接受回调信息*/
        return connectionFactory;
    }


    /**
     * 交换机设置
     * 开启了延时消息
     * @return
     */
    @Bean
    public DirectExchange defaultExchange() {
        DirectExchange directExchange = new DirectExchange(EXCHANGE, true, false);
        directExchange.setDelayed(true);/**只需简单一步开启延时消息,md找了好久,原来这么简单*/
        return directExchange;
    }

    /**
     * 队列设置
     * @return
     */
    @Bean
    public Queue notifyQueue() {
        return new Queue(QUEUE,true);/**消息持久化*/
    }

    /**
     * 绑定队列到交换机
     * @return
     */
    @Bean
    public Binding bindingNotify() {
        return BindingBuilder.bind(notifyQueue()).to(defaultExchange()).with(ROUTING);
    }

}

 rabbitMQ默认是不开启delayed功能的哟,所以同学们还需要到官网或者githup上面下载插件:

 

命令行: rabbitmq-plugins enable rabbitmq_delayed_message_exchange
 

#安装插件 https://github.com/rabbitmq/rabbitmq-delayed-message-exchange 

 

#插件是有版本要求的哦

 

下面贴发送的代码,随便用了个http入口:

package com.fengbaogu.web;

import com.fengbaogu.config.RabbitMQConfig;
import org.springframework.amqp.AmqpException;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageDeliveryMode;
import org.springframework.amqp.core.MessagePostProcessor;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.support.CorrelationData;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.UUID;

/**
 * Created by LiaoKe on 2017/5/2.
 */
@RestController
public class TestController implements RabbitTemplate.ConfirmCallback{


    /**
     * 使用RabbitTemplate发送消息
     */
    private RabbitTemplate rabbitTemplate;

    /**
     * 构造方法
     * @param rabbitTemplate
     */
    public TestController(RabbitTemplate rabbitTemplate){
        this.rabbitTemplate = rabbitTemplate;
        //设置消费回调
        this.rabbitTemplate.setConfirmCallback(this);
    }

    private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");


    /**
     * 向延迟队列中发送消息
     * @param msg
     * @return
     */
    @RequestMapping("send")
    public String send3(String msg){
        String uuid = UUID.randomUUID().toString();
        CorrelationData correlationId = new CorrelationData(uuid);
        rabbitTemplate.convertAndSend(RabbitMQConfig.EXCHANGE,RabbitMQConfig.ROUTING , msg, new MessagePostProcessor() {
                    @Override
                    public Message postProcessMessage(Message message) throws AmqpException {
                        message.getMessageProperties().setDelay(20000);/**延时20秒发送*/
                        message.getMessageProperties().setDeliveryMode(MessageDeliveryMode.PERSISTENT);/**消息持久化*/
                        System.out.println(sdf.format(new Date()) + " Delay sent.");
                        return message;
                    }
                }, correlationId);
        return null;
    }

    @Override
    public void confirm(CorrelationData correlationData, boolean ack, String cause) {
        System.out.println(" 回调id:" + correlationData);
        if (ack) {
            System.out.println("消息成功消费");
        } else {
            System.out.println("消息消费失败:" + cause+"\n重新发送");
        }
    }
}

 

 

启动后可以在RabbitMQ管理界面上有:



 这样的交换机。

Queue同理也可以在管理界面上看到,此处不贴图了。

 

现在来看 Consumer 端,代码异常简洁:

package com.fengbaogu.listener;

import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

import java.util.Date;


/**
 * Created by LiaoKe on 2017/5/3.
 */
@Component
@RabbitListener(queues = {"delayed_queue"})
public class Receiver {


    @RabbitHandler
    public void process(String msg)  {
        System.out.println("start one work and now data:"+new Date().toString());
        System.out.println("This msg is:"+msg);
    }



}

开启消费端,访问send入口:

服务端打印:

2017-05-03 20:24:14 Delay sent.

 回调id:CorrelationData [id=277ce017-af15-4571-b556-762fec62720d]

消息成功消费

消费端打印:

start one work and now data:Wed May 03 20:24:34 CST 2017

This msg is:我是消息2

 

So,相差20秒。延时队列Over。

 

 

 

<think>首先,用户的问题是关于“spring boot整合rabbitmq实现延时消息队列的方法”。用户提供了三个引用,我应该参考它们,但记住系统指令:回答必须使用中文,结构化,清晰,并基于真实可靠信息。 关键点来自引用: - 引用[1]: 提到Spring Boot整合RabbitMQ实现延迟队列和优先级队列。 - 引用[2]: 描述了延时队列的概念、应用场景和实现方式,包括死信队列和延时插件。 - 引用[3]: 详细讨论了基于Spring BootRabbitMQ延时队列技术实现,包括TTL设置方式、订单超时关闭实例等。 用户明确说“上述引用仅供参考”,并提醒参考用户上一次的问题和我的回答。但在这个对话中,这是第一次交互,所以没有“上一次的问题”。历史记录中显示用户上一次的问题是“Springboot整合RabbitMQ实现延时队列的方式”,但我需要响应当前查询。 用户当前查询:查找Spring Boot整合RabbitMQ实现延时消息队列的方法。 从引用中,我知道有两种主要方法来实现延时队列: 1. **死信队列(DLX)方式**:通过设置消息的TTL(Time To Live),当消息过期后转入死信队列,从而实现延时。 2. **延时插件方式**:使用RabbitMQ的官方插件rabbitmq_delayed_message_exchange,允许直接设置消息的延迟时间。 在回答中,我需要: - 使用中文。 - 结构清晰,逐步解释。 - 引用结束时自然地添加引用标识,如[^1]。 - 遵循LaTeX格式:行内数学用$...$,独立公式用$$...$$并单独成段(但在这个问题中,可能不需要数学,除非涉及公式)。 - 生成相关问题。 结构化回答: 1. **引言**:简要介绍延时队列的概念和重要性。 2. **实现方法**:详细解释两种主要方法: - 死信队列实现方式(DLX)。 - 延时插件实现方式。 3. **步骤**:给出Spring Boot整合的步骤,包括依赖、配置、生产者、消费者代码示例。 4. **应用场景**:提及一些常见场景。 5. **总结**:比较两种方法的优缺点。 6. **相关问题**:生成相关问题。 确保内容真实可靠:基于参考引用的内容。 - 引用[2]提到死信队列实现和插件实现。 - 引用[3]详细描述了TTL设置方式和订单超时实例。 代码示例:用户提供了示例格式,我应该包括代码块。 - 在Python示例中,用户使用了三重反引号。 - 这里将是Java代码。 最后,生成相关问题。 完整回答大纲: 1. **延时队列简介** - 定义:延时队列是一种消息队列,消息在发送后延迟一段时间才被消费。 - 应用场景:如商城订单超时取消、提醒服务、收益计算延迟处理等[^2]。 2. **Spring Boot整合RabbitMQ实现延时队列的方法** - **方法一:使用死信队列(DLX)** - 原理:设置消息的TTL,当消息过期后转入死信队列,消费死信队列实现延迟。 - 步骤: 1. 添加依赖。 2. 配置交换机和队列。 3. 生产者:发送消息时设置TTL。 4. 消费者:监听死信队列。 - 代码示例。 - **方法二:使用延时插件(rabbitmq_delayed_message_exchange)** - 原理:安装插件后,创建延迟交换机,直接设置消息的延迟时间。 - 步骤: 1. 安装RabbitMQ插件。 2. 添加依赖。 3. 配置延迟交换机。 4. 生产者:发送消息时指定延迟时间。 5. 消费者:正常监听队列。 - 代码示例。 3. **比较两种方法** - DLX方式:简单,但需要额外队列,TTL不灵活。 - 插件方式:更灵活,但需要安装插件。 4. **相关问题** 引用标识: - 在相关部分添加[^1], [^2], [^3],自然地融入文本。 代码块示例: ```java // Java code for producer ``` 确保LaTeX正确:可能不需要,但如果涉及公式,比如描述TTL,可以用行内格式。 例如,描述TTL时,可以说消息的TTL $t$ 秒。 但在这个上下文中,可能很少。 </think>### Spring Boot 整合 RabbitMQ 实现延时消息队列的方法 Spring Boot 整合 RabbitMQ 实现延时消息队列是一种常见的异步处理方案,适用于需要延迟执行任务的场景。延时队列的核心是消息在发送后延迟一段时间才被消费。根据参考引用,实现方法主要有两种:**死信队列(DLX)方式**和**延时插件方式**。我将从原理到步骤逐步解释,确保内容清晰可靠。 #### 1. **延时队列简介** 延时队列允许消息在队列中等待指定时间后才被消费者处理。典型应用场景包括: - 商城订单超时未支付自动取消[^2]。 - 使用权限到期前十分钟提醒用户[^2]。 - 收益项目,投入后一段时间后产生收益[^2]。 在 RabbitMQ 中,延迟时间单位通常是毫秒(ms),例如消息延迟30分钟可设置为 $t = 1800000$ ms。 #### 2. **实现方法一:使用死信队列(DLX)** 死信队列是一种间接实现延时的方式:设置消息的TTL(Time To Live), 当消息过期后自动转入死信队列,消费者监听死信队列实现延迟消费。适用于不需要精确延迟的场景[^2][^3]。 **步骤及代码示例:** 1. **添加依赖**:在 Spring Boot 项目的 `pom.xml` 中添加 RabbitMQSpring Boot Starter 依赖。 ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-amqp</artifactId> </dependency> ``` 2. **配置交换机和队列**:在 `application.yml` 文件中配置 RabbitMQ 连接和交换机。 ```yaml spring: rabbitmq: host: localhost port: 5672 username: guest password: guest ``` 3. **创建配置类**:定义普通队列、死信交换机和死信队列。使用 `@Configuration` 注解。 ```java import org.springframework.amqp.core.*; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class RabbitMQConfig { // 定义普通队列,并设置死信交换机和路由键 @Bean public Queue normalQueue() { return QueueBuilder.durable("normal.queue") .withArgument("x-dead-letter-exchange", "dlx.exchange") // 死信交换机 .withArgument("x-dead-letter-routing-key", "dlx.routingkey") // 死信路由键 .build(); } // 定义死信队列 @Bean public Queue dlxQueue() { return new Queue("dlx.queue", true); } // 定义死信交换机 @Bean public DirectExchange dlxExchange() { return new DirectExchange("dlx.exchange"); } // 绑定死信交换机和死信队列 @Bean public Binding dlxBinding() { return BindingBuilder.bind(dlxQueue()).to(dlxExchange()).with("dlx.routingkey"); } } ``` 4. **消息生产者**:发送消息时设置 TTL(延迟时间)。TTL 单位为毫秒。 ```java import org.springframework.amqp.rabbit.core.RabbitTemplate; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @Component public class MessageProducer { @Autowired private RabbitTemplate rabbitTemplate; public void sendDelayedMessage(String message, long delayTime) { MessageProperties properties = new MessageProperties(); properties.setExpiration(String.valueOf(delayTime)); // 设置TTL,例如30000ms表示30秒 Message msg = new Message(message.getBytes(), properties); rabbitTemplate.send("normal.queue", msg); } } ``` 5. **消息消费者**:监听死信队列处理延迟消息。 ```java import org.springframework.amqp.rabbit.annotation.RabbitListener; import org.springframework.stereotype.Component; @Component public class MessageConsumer { @RabbitListener(queues = "dlx.queue") public void handleMessage(String message) { System.out.println("收到延迟消息: " + message); // 处理业务逻辑 } } ``` **原理总结**: - 生产者发送消息到 `normal.queue`,消息在队列中等待直到 TTL 过期。 - 过期后,消息转入死信交换机 `dlx.exchange`,路由到 `dlx.queue`。 - 消费者消费 `dlx.queue` 的消息,实现延迟处理[^2][^3]。 **优点**:无需额外插件,易于实现。 **缺点**:TTL 不支持动态设置单个消息的延迟时间,灵活性较低。 #### 3. **实现方法二:使用延时插件(官方推荐)** RabbitMQ 官方提供了 `rabbitmq_delayed_message_exchange` 插件,允许直接设置消息的延迟时间。适用于需要精确延迟的场景[^2][^3]。 **步骤及代码示例:** 1. **安装 RabbitMQ 插件**: - 下载插件:从 [RabbitMQ 插件页面](https://github.com/rabbitmq/rabbitmq-delayed-message-exchange) 获取 `.ez` 文件。 - 安装命令:`rabbitmq-plugins enable rabbitmq_delayed_message_exchange`(RabbitMQ 需运行中)。 - 重启 RabbitMQ 服务。 2. **添加依赖**:同方法一,使用 `spring-boot-starter-amqp`。 3. **配置延迟交换机**:在配置类中定义延迟交换机。 ```java @Configuration public class RabbitMQConfig { // 定义延迟交换机,类型为 x-delayed-message @Bean public CustomExchange delayedExchange() { Map<String, Object> args = new HashMap<>(); args.put("x-delayed-type", "direct"); // 交换机类型 return new CustomExchange("delayed.exchange", "x-delayed-message", true, false, args); } // 定义队列 @Bean public Queue delayedQueue() { return new Queue("delayed.queue", true); } // 绑定队列到延迟交换机 @Bean public Binding delayedBinding() { return BindingBuilder.bind(delayedQueue()).to(delayedExchange()).with("delayed.routingkey").noargs(); } } ``` 4. **消息生产者**:发送消息时指定延迟时间(单位毫秒)。 ```java @Component public class MessageProducer { @Autowired private RabbitTemplate rabbitTemplate; public void sendDelayedMessage(String message, long delayTime) { rabbitTemplate.convertAndSend("delayed.exchange", "delayed.routingkey", message, msg -> { msg.getMessageProperties().setHeader("x-delay", delayTime); // 设置延迟时间 return msg; }); } } ``` 5. **消息消费者**:监听队列处理消息。 ```java @Component public class MessageConsumer { @RabbitListener(queues = "delayed.queue") public void handleMessage(String message) { System.out.println("收到精确延迟消息: " + message); // 处理业务逻辑 } } ``` **原理总结**: - 生产者发送消息时,通过 `x-delay` 头指定延迟时间。 - 消息存储在延迟交换机中,延迟结束后路由到队列。 - 消费者直接消费队列消息[^2][^3]。 **优点**:支持动态延迟时间,灵活性高。 **缺点**:需安装插件,部署稍复杂。 #### 4. **方法比较与选择建议** - **死信队列方式**:适合简单场景,延迟时间固定或范围小。实现门槛低[^3]。 - **延时插件方式**:适合复杂场景,延迟时间可变性强。推荐用于生产环境[^2]。 - **性能考虑**:插件方式减少了队列切换,性能略优。RabbitMQ 默认支持高吞吐量。 #### 5. **常见问题与应用** - **注意事项**: - 死信队列中,TTL 单位为毫秒,但队列级别的 TTL 对所有消息生效。 - 插件方式需确保 RabbitMQ 版本匹配(如 v3.8+)。 - **应用场景扩展**:可用于订单超时关闭、定时任务提醒等[^2][^3]。 总之,Spring Boot 整合 RabbitMQ 实现延时消息队列的核心在于选择合适的方法。死信队列适合入门,延时插件提供更专业的解决方案。参考引用中提供了详细的实现案例[^1][^2][^3]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值