springboot 使用RabbitMQ实现延迟队列

RabbitMQ延迟消息实现方式

image

延迟任务通过消息的TTL和Dead Letter Exchange来实现。我们需要建立2个队列,一个用于发送消息,一个用于消息过期后的转发目标队列。

生产者输出消息到Queue1,并且这个消息是设置有有效时间的,比如60s。消息会在Queue1中等待60s,如果没有消费者收掉的话,它就是被转发到Queue2,Queue2有消费者,收到,处理延迟任务。

具体创建步骤如下:

1. 创建2个路由、2个队列:

路由:Exchange1、Exchange2。(均为普通路由)

队列:Queue1、Queue2。(Queue1为特殊队列,Queue2为普通队列)

Queue1需要设置 Dead letter exchange 参数(名称:x-dead-letter-exchange,值为刚才创建的Exchange2),当Queue1中的消息过期后,通过路由Exchange2转发。

2. 绑定

将Exchange1与Queue1绑定,Exchange2与Queue2绑定

 

Java实现

1.引入jar包

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

2.创建路由、队列 (这部分在程序运行前手动执行,运行一次即可。也可以通过rabbit管理页面创建)


import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeoutException;

import org.junit.Test;

import com.rabbitmq.client.BuiltinExchangeType;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;

/**
 * 创建路由、队列,并绑定  (这个类不是Junit测试类,@Test标注的方法类似于main方法可直接运行)
 */
public class DlConfig {

    final static String firstExchange = "firstExchange";
    final static String firstQuque = "firstQuque";
    final static String twoExchange = "twoExchange";
    final static String twoQueue = "twoQueue";
    final static String routingKey = "ddd";
    
    /**
     * 手动执行,创建路由、队列
     */
    @Test
    public void binding() throws IOException, TimeoutException{
        
        //建立连接,创建通道
        ConnectionFactory fc = new ConnectionFactory();
        fc.setHost("localhost");
        fc.setPort(5672);
        fc.setUsername("guest");
        fc.setPassword("guest");
        
        Connection conn = fc.newConnection();
        Channel channel = conn.createChannel();
        
        channel.exchangeDelete(firstExchange);  //删除路由
        channel.exchangeDelete(twoExchange);
        channel.exchangeDeclare(firstExchange, BuiltinExchangeType.DIRECT);  //创建路由
        channel.exchangeDeclare(twoExchange, BuiltinExchangeType.DIRECT);
        
        channel.queueDelete(firstQuque);  //删除队列
        Map<String,Object> map = new HashMap<String,Object>();  //设置队列参数
        map.put("x-dead-letter-exchange", twoExchange);
        channel.queueDeclare(firstQuque, true, false, false, map);  //创建队列
        
        channel.queueDelete(twoQueue);
        channel.queueDeclare(twoQueue, true, false, false, null);        
        
        channel.queueBind(firstQuque, firstExchange, routingKey);  //绑定路由、队列
        channel.queueBind(twoQueue, twoExchange, routingKey);
         
        channel.close();
        conn.close();
    }

    
}

3,消息发送者


import java.time.LocalDateTime;

import org.springframework.amqp.AmqpException;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessagePostProcessor;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * 消息生产者
 */
@Component
public class DlProducer {
    
    /** 引入rabbit的操作模板 */
    @Autowired
    RabbitTemplate rabbitTemplate;
    
    /**
     * 发送信息
     */
    public void sender(){
        
        MessagePostProcessor msg = new MessagePostProcessor() {
            @Override
            public Message postProcessMessage(Message msg) throws AmqpException {
                // 设置延迟毫秒值
                msg.getMessageProperties().setExpiration("5000");
                return msg;
            }
        };
        rabbitTemplate.convertAndSend(DlConfig.firstExchange, DlConfig.routingKey, "哈哈哈哈哈"+LocalDateTime.now(), msg);
        
        
        // 另一种写法 使用拉姆达表达式
        rabbitTemplate.convertAndSend(DlConfig.firstExchange, DlConfig.routingKey, "哈哈哈哈哈"+LocalDateTime.now(), message -> {
            // 设置延迟毫秒值
            message.getMessageProperties().setExpiration(String.valueOf(5000));
            return message;
        });
        
    }

}

4.消息接收者


import java.time.LocalDateTime;

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

/**
 * 消息消费者
 */
@Component
public class DlConsumer {
    
    /**
     * 接收消息,监听 twoQueue 队列
     */
    @RabbitListener(queues = "twoQueue")
    public void ls(String message){
        System.out.println(message+" | "+LocalDateTime.now());
    }
    

}

运行结果:

哈哈哈哈哈2018-07-26T18:24:06.981 | 2018-07-26T18:24:11.993
哈哈哈哈哈2018-07-26T18:24:06.988 | 2018-07-26T18:24:11.995

 

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
使用 Spring Boot 实现 RabbitMQ 延时队列,可以使用 RabbitMQ 的插件 RabbitMQ Delayed Message Exchange(rabbitmq_delayed_message_exchange)。 以下是实现步骤: 1. 首先,需要在 Maven 或 Gradle 添加 RabbitMQ 的 Java 客户端库和 RabbitMQ Delayed Message Exchange 插件的依赖。例如,在 Maven 添加以下依赖: ``` <dependency> <groupId>com.rabbitmq</groupId> <artifactId>amqp-client</artifactId> <version>5.11.0</version> </dependency> <dependency> <groupId>net._95point2.fmq</groupId> <artifactId>rabbitmq-delayed-message-exchange</artifactId> <version>2.2.0</version> </dependency> ``` 2. 在 Spring Boot 应用程序配置 RabbitMQ 连接属性。可以使用 application.yml 或 application.properties 文件来配置。 ``` spring: rabbitmq: host: localhost port: 5672 username: guest password: guest ``` 3. 创建一个配置类来配置 RabbitMQ Exchange。在这个类,将使用 `CustomExchange` 类来创建一个延时 Exchange。需要为这个 Exchange 指定一个名称和类型,并且设置其参数 `x-delayed-type` 为要延迟的消息的 Exchange 类型,例如 `direct` 或 `topic`。 ``` @Configuration public class RabbitMQConfig { @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); } } ``` 4. 创建一个生产者来发送延迟消息。在这个生产者类,注入 RabbitTemplate 并使用其 convertAndSend 方法发送消息。需要为消息设置一个 Routing Key,它将用于将消息路由到正确的队列。还需要为消息设置一个延迟时间,将消息发送到刚刚创建的 Exchange 。 ``` @Component public class Producer { @Autowired private RabbitTemplate rabbitTemplate; public void sendDelayedMessage(String message, int delay) { rabbitTemplate.convertAndSend("delayed_exchange", "delayed_queue", message, message1 -> { message1.getMessageProperties().setDelay(delay); return message1; }); } } ``` 5. 创建一个消费者来处理延迟消息。在这个消费者类,注入 RabbitTemplate 并使用其 receiveAndConvert 方法来接收消息。需要为消费者设置一个队列,并将这个队列绑定到刚刚创建的 Exchange 上。 ``` @Component public class Consumer { @RabbitListener(queues = "delayed_queue") public void receiveMessage(String message) { System.out.println("Received message: " + message); } @Bean public Queue delayedQueue() { return QueueBuilder.durable("delayed_queue") .withArgument("x-dead-letter-exchange", "") .withArgument("x-dead-letter-routing-key", "real_queue") .build(); } @Bean public Binding binding() { return BindingBuilder.bind(delayedQueue()).to(delayedExchange()).with("delayed_queue").

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值