【SpringBoot】43、SpringBoot中整合RabbitMQ实现延时队列(延时插件篇)「建议收藏」

【SpringBoot】43、SpringBoot中整合RabbitMQ实现延时队列(延时插件篇)「建议收藏」一、介绍1、什么是延时队列?延时队列即就是放置在该队列里面的消息是不需要立即消费的,而是等待一段时间之后取出消费2、适用场景(1)商城订单超时未支付,取消订单(2)使用权限到期前十分钟提醒用户(3)收益项目,投入后一段时间后产生收益二、实现方式从以上场景中,我们可以看出,延时队列的主要功能就是在指定的时间之后做指定的事情,那么,我们思考有哪些工具我们可以使用?1、Redis监听过期Key可以参考我的博客【SpringBoot】三十五、SpringBoot整合Redis监听Ke

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE稳定放心使用

死信队列实现篇,参考文章:【SpringBoot】60、SpringBoot中整合RabbitMQ实现延时队列(死信队列篇)

一、介绍

  • 1、什么是延时队列?
    延时队列即就是放置在该队列里面的消息是不需要立即消费的,而是等待一段时间之后取出消费
  • 2、适用场景
    (1)商城订单超时未支付,取消订单
    (2)使用权限到期前十分钟提醒用户
    (3)收益项目,投入后一段时间后产生收益

二、实现方式

从以上场景中,我们可以看出,延时队列的主要功能就是在指定的时间之后做指定的事情,那么,我们思考有哪些工具我们可以使用?

  • 1、Redis 监听过期 Key

可以参考我的博客【SpringBoot】三十五、SpringBoot整合Redis监听Key过期事件

https://lizhou.blog.csdn.net/article/details/109238083
  • 2、RabbitMQ等实现延时队列

这也是本片文章中要讲的知识点,使用 RabbitMQ 实现延时队列有两种方式

(1)利用两个特性: Time To Live(TTL)、Dead Letter Exchanges(DLX)
(2)利用 RabbitMQ 中的插件 x-delay-message

本文主要讲解第二种方式,使用插件的方式

三、下载插件

RabbitMQ 实现了一个插件 x-delay-message 来实现延时队列,我们可以从 这里 下载到它

https://www.rabbitmq.com/community-plugins.html

选择 rabbitmq_delayed_message_exchange 插件,如图所示
下载插件
下载插件
选择 .ez 格式的文件下载,下载后放置 RabbitMQ 的安装目录下的 plugins 目录下,如我的路径为

D:\Program Files\RabbitMQ Server\rabbitmq_server-3.7.16\plugins

执行命令

rabbitmq-plugins enable rabbitmq_delayed_message_exchange

安装插件完成

四、在SpringBoot整合RabbitMQ

1、引入 RabbitMQ 依赖

<!-- rabbitmq消息队列 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-amqp</artifactId>
</dependency>

2、配置 RabbitMQ 信息

spring:
  rabbitmq:
    host: 127.0.0.1
    port: 5672
    username: guest
    password: guest
    listener:
      simple:
        # 手动ACK 不开启自动ACK模式,目的是防止报错后未正确处理消息丢失 默认 为 none
        acknowledge-mode: manual

3、RabbitMQ 常量类

package com.asurplus.common.rabbitmq;

/**
 * rabbit常量类
 *
 * @Author Lizhou
 */
public final class RabbitConst {

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

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

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

}

4、RabbitMQ 配置类

package com.asurplus.common.rabbitmq;

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;

/**
 * rabbitmq配置类
 *
 * @Author Lizhou
 */
@Configuration
public class RabbitConfig {

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

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

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

5、RabbitMQ 生产者

package com.asurplus.common.rabbitmq;

import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * rabbitMq生产者
 *
 * @Author Lizhou
 */
@Component
@Slf4j
public class RabbitProducer {

    @Autowired
    private RabbitTemplate rabbitTemplate;

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

6、RabbitMQ 消费者

package com.asurplus.common.rabbitmq;

import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

import java.io.IOException;

/**
 * activeMq消费者
 *
 * @Author Lizhou
 */
@Component
@Slf4j
public class RabbitConsumer {

    /**
     * 接收消息
     *
     * @param object 监听的内容
     */
    @RabbitListener(queues = RabbitConst.DELAY_QUEUE)
    public void cfgUserReceiveDealy(Object object, Message message, Channel channel) throws IOException {
		// 通知 MQ 消息已被接收,可以ACK(从队列中删除)了
        channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
        try {
            log.info("接受消息:{}", object.toString());
        } catch (Exception e) {
            log.error(e.getMessage());
            /**
             * basicRecover方法是进行补发操作,
             * 其中的参数如果为true是把消息退回到queue但是有可能被其它的consumer(集群)接收到,
             * 设置为false是只补发给当前的consumer
             */
            channel.basicRecover(false);
        }
    }
}

五、测试

package com.asurplus;

import com.asurplus.common.rabbitmq.RabbitProducer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@SpringBootApplication
@RestController
public class RabbitmqApplication {

    @Autowired
    private RabbitProducer product;

    @GetMapping("init")
    public void init() {
        String message1 = "这是第一条消息";
        String message2 = "这是第二条消息";
        product.sendDelayMessage(message1, 5000);
        product.sendDelayMessage(message2, 10000);
    }

    public static void main(String[] args) {
        SpringApplication.run(RabbitmqApplication.class, args);
    }

}

通过测试,第一条消息在 5s后接收到,第二条消息在 10s后接收到,说明我们的延时队列已经成功

如您在阅读中发现不足,欢迎留言!!!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/188346.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • tabnine激活码获取【2021免费激活】[通俗易懂]

    (tabnine激活码获取)本文适用于JetBrains家族所有ide,包括IntelliJidea,phpstorm,webstorm,pycharm,datagrip等。https://javaforall.net/100143.htmlIntelliJ2021最新激活注册码,破解教程可免费永久激活,亲测有效,上面是详细链接哦~M…

    2022年3月20日
    313
  • android之Widget开发详解实例三

    之前已经有过两篇写Widget的了,实例一和实例二,如果乍看这篇有难度,可以先看看前两个比较简单的.本篇完成项目是一个小的心情记录器整体效果图如下:这里我们是通过点击桌面的widget弹出记录心情的activity的,实现方法如下:Intent intentClick = new Intent(context, update.class); Pending

    2022年3月10日
    40
  • acwing-2180. 最长递增子序列问题(最大流+拆点+最长上升子序列)

    acwing-2180. 最长递增子序列问题(最大流+拆点+最长上升子序列)给定正整数序列 x1,⋯,xn。计算其最长递增子序列的长度 s。计算从给定的序列中最多可取出多少个长度为 s 的递增子序列。(给定序列中的每个元素最多只能被取出使用一次)如果允许在取出的序列中多次使用 x1 和 xn,则从给定序列中最多可取出多少个长度为 s 的递增子序列。注意:递增指非严格递增。输入格式第 1 行有 1 个正整数 n,表示给定序列的长度。接下来的 1 行有 n 个正整数 x1,⋯,xn。输出格式第 1 行输出最长递增子序列的长度 s。第 2 行输出可取出的长度为 s 的

    2022年8月9日
    6
  • docker 启动容器出现 Exited[通俗易懂]

    有时候在启动容器的时候,启动没报错,但是在执行dockerps-a时发现刚启动的容器状态为Exited(1),这个时候查看日志dockerlogs-f-t–tail20容器ID,发现报chown:changingownershipof’.’:Permissiondenied提示没有权限,这个时候将容器删除,在执行容器启动的命令中加入–privi…

    2022年4月17日
    1.3K
  • 荣耀路由2 虚拟服务器,2019年性价比之王旗舰路由器—荣耀路由PRO2评测「建议收藏」

    大家好我是搞机大表姐,今天大表姐给大家带来的是和荣耀V20一起发布的全新旗舰路由器—荣耀路由PRO2,时隔三年终于迎来了荣耀路由器PRO的升级版,相比上一代荣耀路由器PRO2带来了“六”大技术的升级,更是支持30天用不爽就退,且明哥还在发布会发下战书“600元内路由器任意挑战”的狠话让这次发布的路由PRO2带来了更足的底气,那么具体的实际表现如何呢,请看下面大表姐为大家带来的评测。按照国际惯…

    2022年4月10日
    184
  • 前女友婚礼,python破解婚礼现场的WIFI,把名称改成了[通俗易懂]

    前女友婚礼,python破解婚礼现场的WIFI,把名称改成了[通俗易懂]python小哥哥,参加前女友婚礼,破解了婚礼现场的WIFI,还把WiFi的名称给改成了。。。

    2022年6月12日
    35

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号