消息队列之延迟队列超详细入门教程速看

一. 延迟队列的应用场景

1.具体应用

关于消息队列我们已经很熟悉了,我们知道在消息队列中可以实现延迟队列效果,那你知道延迟队列有哪些使用场景吗?这里我给大家总结了延迟队列的几个经典使用场景,看看你的项目中是否涉及到了。

  • 淘宝七天自动确认收货。在我们签收商品后,物流系统会在七天后延时发送一个消息给支付系统,通知支付系统将货款打给商家,这个过程持续七天,就是使用了消息中间件的延迟推送功能;

  • 订单在十分钟之内未支付则自动取消;

  • 新创建的店铺,如果在十天内都没有上传过商品,则自动发送消息提醒;

  • 用户注册成功后,如果三天内没有登陆则进行短信提醒

  • 用户发起退款,如果三天内没有得到处理则通知相关运营人员;

  • 预定会议后,需要在预定的时间点前十分钟通知各个与会人员参加会议。

2.延迟队列简介

  • RabbitMQ 3.6.x 之前,我们一般采用死信队列+TTL过期时间来实现延迟队列,通过TTL+死信队列完成。

  • 从RabbitMQ 3.6.x 开始,RabbitMQ 官方直接提供了延迟队列插件,可以下载放置到 RabbitMQ 根目录下的 plugins 下,这样就可以很轻松的实现延迟队列效果了。

那么延迟队列到底该怎么使用呢?今天我就通过一个小案例来带大家实现一下。

二. 本次需求

以下是我们今天要实现的基本需求。

  • 用户注册成功后,如果三天内没有登陆则进行短信提醒。

你现在有没有什么实现思路呢?别急,请跟着我一点点往下看吧。

三. 安装配置RabbitMQ

我们采用Docker来安装配置RabbitMQ及其插件,如果你对Docker还不了解,可以参考如下视频教程

Docker快速入门教程

1.Docker 安装 RabbitMQ

1.1 查找RabbitMQ镜像

docker search rabbitmq

1.2 拉取RabbitMQ镜像

docker pull rabbitmq               (镜像未配有控制台)
docker pull rabbitmq:management    (镜像配有控制台)

注意:

  • rabbitmq是官方镜像,该镜像不带控制台。如果要安装带控制台的镜像,需要在拉取镜像时附带;

  • tag标签,例如:management;

  • tag标签可以通过https://hub.docker.com//rabbitmq?tab=tags来查询。

1.3 启动RabbitMQ

docker run -d --name rabbitmq -e RABBITMQ_DEFAULT_USER=admin -e RABBITMQ_DEFAULT_PASS=admin -p 15672:15672 -p 5672:5672 rabbitmq:management

创建容器并运行(15672是管理界面的端口,5672是服务的端口;

这里顺便将管理系统的用户名和密码设置为admin admin;

-e RABBITMQ_DEFAULT_USER=admin -e RABBITMQ_DEFAU LT_PASS=admin.

1.4 停止RabbitMQ

docker stop rabbitmq

1.5 重启 RabbitMQ 容器

docker restart rabbitmq

1.6 查看 RabbitMQ 容器进程信息

docker top rabbitmq

2.安装延迟队列插件

2.1 下载RabbitMQ相匹配的插件版本

https://github.com/rabbitmq/rabbitmq-delayed-message-exchange/

https://github.com/rabbitmq/rabbitmq-delayed-message-exchange/ releases/tag/v3.8.0

2.2 上传插件到服务器的/root文件夹下,然后进行如下操作

#拷贝到rabbitmq容器 773067241f96 中
docker cp rabbitmq_delayed_message_exchange-3.8.9-0199d11c.ez rabbitmq:/plugins

#进入容器
docker exec -it rabbitmq /bin/bash

#启用插件
rabbitmq-plugins enable rabbitmq_delayed_message_exchange

#查看
rabbitmq-plugins list

#重新启动容器
docker restart rabbitmq

四. 实现延迟消息

1.基本需求

用户注册成功后,如果三天内没有登陆则进行短信提醒。本需求基本架构如下图所示:

2.生产者Provider

Provider部分代码如下所示:

**
 * @ClassName UserController
 * @Description TODO  用户管理业务模块
 * @Author 千锋-南京-Wilson
 * @Version 1.0
 */
@Controller
@RequestMapping("user")
@Slf4j
public class UserController {
    /**消息队列*/
    @Autowired
    private AmqpTemplate amqpTemplate;
    /**
     * 注册功能
     * @return
     */
    @ResponseBody
    @GetMapping("register")
    public String register(@RequestParam("uname") String uname){
        // 延迟的时间毫秒 ms
        int delayTime=8000;
       log.info("用户业务逻辑注册成功--》"+uname+"\t"+new Date().toString()+"\t"+delayTime+"毫秒");

        //队列发送 邮件  延迟 delayTime
        amqpTemplate.convertAndSend("delayed.exchange.user.register",
                "delayed.key.user.register",uname,msg->{
                    msg.getMessageProperties().setDelay(delayTime);
                    return  msg;
                });
        return "用户注册成功";
    }

3.交换机配置

交换机代码如下所示:

package com.qfjy.config.example5;
**
 * @ClassName UserDelayedQueueConfig
 * @Description TODO  用户延迟队列配置
 * @Author 千锋-南京-Wilson
 * @Version 1.0
 */
@Configuration
public class UserDelayedQueueConfig {
    /**
     * TODO 1、定义交换机   delayed.exchange.user.register
     *      2、定义队列     delayed.queue.user.register
     *      3、路由KEY      delayed.key.user.register
     *      4、队列绑定交换机路由
     */
    /**
     * TODO 定义交换机
     */
    @Bean
    public CustomExchange delayedExchangeUserRegister(){
        /**
         * String name, 交换机名称
         * String type,  交换机消息类型(x-delayed-message)
         * boolean durable, 是否持久化
         * boolean autoDelete,是否删除
         * Map<String, Object> arguments  // 队列中的消息什么时候会自动被删除?
         *   arguments.put("x-message-ttl",10000); //设置过期时间
         *   arguments.put("x-expires", 10000); //x-expires用于当多长时间没有消费者访问该队列的时候,该队列会自动删除,
         *   arguments.put("x-max-length", 4); //x-max-length:用于指定队列的长度,如果不指定,可以认为是无限长,例如指定队列的长度是4,当超过4条消息,前面的消息将被删除,给后面的消息腾位
         */
        Map<String, Object> arguments=new HashMap<>();
        arguments.put("x-delayed-type","direct");
        return new CustomExchange("delayed.exchange.user.register","x-delayed-message",
                true,false,arguments);
    }
    /**
     *  TODO 定义队列 delayed.queue.user.register
     */
    @Bean
     public Queue delayedQueueUserRegister(){
         return new Queue("delayed.queue.user.register");
     }

    /**
     * TODO 3 绑定 交换机 队列 路由KEY
     * @return
     */
     @Bean
     public Binding bindDelayedQueueDelayedExchangeUserRegister(
             Queue delayedQueueUserRegister,
             CustomExchange delayedExchangeUserRegister){

         return BindingBuilder.bind(delayedQueueUserRegister).to(delayedExchangeUserRegister).with("delayed.key.user.register").noargs();

     }
}

4.消费者Consumer

消费者部分的代码如下所示:

@Service
@Slf4j
public class UserRegisterServiceImpl {
    /**
     * 用户 邮件发送
     */
    @RabbitListener(queues = {"delayed.queue.user.register"})
    public void sendEmail(String uname){
        log.info("用户发送邮件成功--》"+uname+"\t"+new Date().toString());
    }
}

这样我们通过以上配置和代码,就可以实现这个基本需求了。

如果你想更好地学习并掌握Java相关的更多知识和用法,大家可以扫码获取相关资源哦。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

威哥爱编程(马剑威)

你的鼓励是我创作的最大动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值