RabbitMQ利用延迟插件实现延时队列

摘要:本文使用docker部署rabbitmq,利用插件,使用SpringBoot来整合rabbitmq简单实现延时队列

docker部署rabbitmq

docker安装步骤略
本文使用rabbitmq:3.9.1版本

部署rabbimq

1.拉取镜像
docker pull rabbitmq:3.9.1
2.启动容器
docker run  -e RABBITMQ_DEFAULT_USER=root  -e RABBITMQ_DEFAULT_PASS=123456  --name mq  --hostname mq1  -p 15672:15672  -p 5672:5672  -d  rabbitmq:3.9.1
-e:设置参数配置(初始用户登录账号密码)
-p:端口映射
3.进入rabbitmq容器开启web访问插件
docker exec -it mq /bin/bash
进入容器后执行命令开启插件
rabbitmq-plugins enable rabbitmq_management
至此docker部署rabbitmq完毕,可访问xx.xx.xx.xx:15672来访问

下载添加延迟插件

本文使用3.9.1版本rabbitmq,提供相应插件(3.9.x都可使用)
下载地址

链接:https://pan.baidu.com/s/1O1CbgsmkAIlUYBHkE_6PDw?pwd=ut5z 
提取码:ut5z

下载完成后需将文件传入容器

1.传入文件(文件存放路径按实际情况修改)
docker cp /root/rabbitmq_delayed_message_exchange-3.9.0.ez 3f3bf8b3b359:/plugins
2.进入容器
docker exec -it mq /bin/bash
3.开启插件
rabbitmq-plugins enable rabbitmq_delayed_message_exchange
4.重启容器
docker restart mp

进入rabbitmq的web管理页面查看是否生效

新建交换机时,type中出现该选项就代表生效

SpringBoot整合Rabbitmq使用延时队列

添加依赖

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

添加配置文件信息

spring:
  rabbitmq:
    host: xx.xx.xx.xx
    port: 5672
    username: root
    password: 123456

编写rabbitmq配置文件初始化交换机,队列以及队列和交换机的绑定

package com.syb.springboottestdemo.config;

import com.syb.springboottestdemo.constant.RabbitConstant;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.CustomExchange;
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: syb
* @Description: rabbitmq配置类
* @DateTime: 2022/8/1 11:08
* @Params:
* @Return
*/
@Configuration
public class RabbitConfig {

    /**
     * 延时队列交换机
     *
     * @return
     */
    @Bean
    public CustomExchange delayExchange() {
        Map<String, Object> args = new HashMap<>();
        args.put("x-delayed-type", "direct");
        return new CustomExchange(RabbitConstant.DELAY_EXCHANGE, "x-delayed-message", true, false, args);
    }

    /**
     * 延时队列
     *
     * @return
     */
    @Bean
    public Queue delayQueue() {
        return new Queue(RabbitConstant.DELAY_QUEUE, true);
    }

    /**
     * 给延时队列绑定交换机
     *
     * @return
     */
    @Bean
    public Binding delayBinding(Queue delayQueue, CustomExchange delayExchange) {
        return BindingBuilder.bind(delayQueue).to(delayExchange).with(RabbitConstant.DELAY_KEY).noargs();
    }
}

常量类

package com.syb.springboottestdemo.constant;

public class RabbitConstant {

    /**
     * 交换机
     */
    public static final String DELAY_EXCHANGE = "delay_exchange";

    /**
     * 队列
     */
    public static final String DELAY_QUEUE = "delay_queue";

    /**
     * 路由
     */
    public static final String DELAY_KEY = "delay_key";

}

生产者

package com.syb.springboottestdemo.listener;

import com.syb.springboottestdemo.constant.RabbitConstant;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class RabbitProducer {
    @Autowired
    private RabbitTemplate rabbitTemplate;

    /**
     * 发送消息
     *
     * @param object      发送对象
     * @param millisecond 延时(毫秒)
     */
    public void sendDelayMessage(String object, long millisecond) {
        this.rabbitTemplate.convertAndSend(
                RabbitConstant.DELAY_EXCHANGE,
                RabbitConstant.DELAY_KEY,
                object,
                message -> {
                    message.getMessageProperties().setHeader("x-delay", millisecond);
                    return message;
                }
        );
    }

}

消费者

package com.syb.springboottestdemo.listener;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.rabbitmq.client.Channel;
import com.syb.springboottestdemo.constant.RabbitConstant;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

import java.io.IOException;

@Component
public class RabbitConsumer {
    /**
     * 接收消息
     *
     * @param object 监听的内容
     */
    @RabbitListener(queues = RabbitConstant.DELAY_QUEUE)
    public void cfgUserReceiveDealy(String object, Message message, Channel channel) throws IOException {
        ObjectMapper mapper=new ObjectMapper();
        channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
        try {
            System.out.println(object);
        } catch (Exception e) {
            System.out.println(e);
            /**
             * basicRecover方法是进行补发操作,
             * 其中的参数如果为true是把消息退回到queue但是有可能被其它的consumer(集群)接收到,
             * 设置为false是只补发给当前的consumer
             */
            channel.basicRecover(false);
        }
    }
}

测试一下

package com.syb.springboottestdemo.controller;

import com.syb.springboottestdemo.listener.RabbitProducer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

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

@RestController
public class RabbitDelayController {

    @Autowired
    RabbitProducer rabbitProducer;

    @GetMapping(value = "/sendRabbitMqMessage")
    public void sendDelayMessageTest(){
        Map<String,String> map=new HashMap<>();
        map.put("第一条信息","信息一");
        map.put("第二条信息","信息二");
        rabbitProducer.sendDelayMessage(map.get("第一条信息"),5000);
        rabbitProducer.sendDelayMessage(map.get("第二条信息"),10000);
    }

}

简单测试接口后五秒和十秒时消费者会消费信息,成功实现延时操作

posted @   Cv工程师120621号  阅读(417)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· Vue3状态管理终极指南:Pinia保姆级教程
点击右上角即可分享
微信分享提示

目录导航