springboot使用RabbitMQ实现延时任务

延时队列顾名思义,即放置在该队列里面的消息是不需要立即消费的,而是等待一段时间之后取出消费。
那么,为什么需要延迟消费呢?我们来看以下的场景

订单业务: 在电商/点餐中,都有下单后 30 分钟内没有付款,就自动取消订单。
短信通知: 下单成功后 60s 之后给用户发送短信通知。
失败重试: 业务操作失败后,间隔一定的时间进行失败重试。

本文基于springboot,使用rabbitmq_delayed_message_exchange插件实现延时队列(RabbitMQ及其插件环境安装点此),具体实践如下:

application.properties

spring.rabbitmq.username=root
spring.rabbitmq.password=root
spring.rabbitmq.host=192.168.1.123
spring.rabbitmq.port=5672
spring.rabbitmq.virtual-host=test

XdelayConfig.java

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;

@Configuration
public class XdelayConfig {

    /**
     * 立即消费的队列名称
     */
    public static final String IMMEDIATE_QUEUE_XDELAY = "queue.xdelay.immediate";
    /**
     * 延时的exchange
     */
    public static final String DELAYED_EXCHANGE_XDELAY = "exchange.xdelay.delayed";
    public static final String DELAY_ROUTING_KEY_XDELAY = "routingkey.xdelay.delay";

    /**
     * 创建一个立即消费队列
     *
     * @return
     */
    @Bean
    public Queue immediateQueue() {
        // 第一个参数是创建的queue的名字,第二个参数是是否支持持久化
        return new Queue(IMMEDIATE_QUEUE_XDELAY, true);
    }

    @Bean
    public CustomExchange delayExchange() {
        Map<String, Object> args = new HashMap<String, Object>();
        args.put("x-delayed-type", "direct");
        return new CustomExchange(DELAYED_EXCHANGE_XDELAY, "x-delayed-message", true, false, args);
    }

    /**
     * 把立即消费的队列和延时消费的exchange绑定在一起
     *
     * @return
     */
    @Bean
    public Binding bindingNotify() {
        return BindingBuilder.bind(immediateQueue()).to(delayExchange()).with(DELAY_ROUTING_KEY_XDELAY).noargs();
    }
}

XdelaySender.java 生产者

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

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

/**
 * 生产者
 */
@Component
public class XdelaySender {
    private final static Logger logger = LoggerFactory.getLogger(XdelaySender.class);
    @Autowired
    private RabbitTemplate rabbitTemplate;

    public void send(String msg, int delayTime) {
        logger.info("msg= " + msg + ".delayTime" + delayTime);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        this.rabbitTemplate.convertAndSend(XdelayConfig.DELAYED_EXCHANGE_XDELAY, XdelayConfig.DELAY_ROUTING_KEY_XDELAY, msg, message -> {
            message.getMessageProperties().setDelay(delayTime);
            System.out.println(sdf.format(new Date()) + " Delay sent.");
            return message;
        });
    }
}

XdelayReceiver.java 消费者

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.rabbit.annotation.EnableRabbit;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;

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

/**
 * 消费者
 */
@Component
@EnableRabbit
@Configuration
public class XdelayReceiver {
    private final static Logger logger = LoggerFactory.getLogger(XdelayReceiver.class);

    @RabbitListener(queues = com.example.antchat.rabbitmq.XdelayConfig.IMMEDIATE_QUEUE_XDELAY)
    public void get(String msg) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        logger.info("收到延时消息时间:" + sdf.format(new Date()) + " Delay sent.");
        logger.info("收到延时消息:" + msg);
    }
}

测试

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class RabbitMQController {
    @Autowired
    XdelaySender xdelaySender;
    @RequestMapping("/testRabbit")
    public void testRabbit() {
        xdelaySender.send("我来发一个测试消息,10秒", 10000);//10秒
        xdelaySender.send("我来发一个测试消息,2秒", 2000);//2秒
        xdelaySender.send("我来发一个测试消息,1秒", 2000);//1秒
    }
}

参考博文:

微服务-springboot-rabbitmq:实现延时队列

原文地址:https://www.cnblogs.com/wintercloud/p/10877399.html

时间: 2024-10-10 10:15:29

springboot使用RabbitMQ实现延时任务的相关文章

SpringBoot整合RabbitMQ之典型应用场景实战一

实战前言RabbitMQ 作为目前应用相当广泛的消息中间件,在企业级应用.微服务应用中充当着重要的角色.特别是在一些典型的应用场景以及业务模块中具有重要的作用,比如业务服务模块解耦.异步通信.高并发限流.超时业务.数据延迟处理等. RabbitMQ 官网拜读首先,让我们先拜读 RabbitMQ 官网的技术开发手册以及相关的 Features,感兴趣的朋友可以耐心的阅读其中的相关介绍,相信会有一定的收获,地址可见:http://www.rabbitmq.com/getstarted.html 在阅

springboot学习笔记-6 springboot整合RabbitMQ

一 RabbitMQ的介绍 RabbitMQ是消息中间件的一种,消息中间件即分布式系统中完成消息的发送和接收的基础软件.这些软件有很多,包括ActiveMQ(apache公司的),RocketMQ(阿里巴巴公司的,现已经转让给apache). 消息中间件的工作过程可以用生产者消费者模型来表示.即,生产者不断的向消息队列发送信息,而消费者从消息队列中消费信息.具体过程如下: 从上图可看出,对于消息队列来说,生产者,消息队列,消费者是最重要的三个概念,生产者发消息到消息队列中去,消费者监听指定的消息

springboot系列-springboot整合RabbitMQ

一 RabbitMQ的介绍 RabbitMQ是消息中间件的一种,消息中间件即分布式系统中完成消息的发送和接收的基础软件.这些软件有很多,包括ActiveMQ(apache公司的),RocketMQ(阿里巴巴公司的,现已经转让给apache). 消息中间件的工作过程可以用生产者消费者模型来表示.即,生产者不断的向消息队列发送信息,而消费者从消息队列中消费信息.具体过程如下: 从上图可看出,对于消息队列来说,生产者,消息队列,消费者是最重要的三个概念,生产者发消息到消息队列中去,消费者监听指定的消息

SpringBoot整合RabbitMQ之发送接收消息实战

实战前言 前几篇文章中,我们介绍了SpringBoot整合RabbitMQ的配置以及实战了Spring的事件驱动模型,这两篇文章对于我们后续实战RabbitMQ其他知识要点将起到奠基的作用的.特别是Spring的事件驱动模型,当我们全篇实战完毕RabbitMQ并大概了解一下RabbitMQ相关组件的源码时,会发现其中的ApplicationEvent.ApplicationListener.ApplicationEventPublisher跟RabbitMQ的Message.Listener.R

SpringBoot之RabbitMQ的使用

一 .RabbitMQ的介绍 RabbitMQ是消息中间件的一种,消息中间件即分布式系统中完成消息的发送和接收的基础软件,消息中间件的工作过程可以用生产者消费者模型来表示.即,生产者不断的向消息队列发送信息,而消费者从消息队列中消费信息.具体过程如下: 从上图可看出,对于消息队列来说,生产者.消息队列.消费者是最重要的三个概念,生产者发消息到消息队列中去,消费者监听指定的消息队列,并且当消息队列收到消息之后,接收消息队列传来的消息,并且给予相应的处理.消息队列常用于分布式系统之间互相信息的传递.

SpringBoot整合RabbitMQ入门~~

SpringBoot整合RabbitMQ 入门2020-01-12 创建生产者类,并且在yml配置文件中配置5要素连接MQ yml配置文件 spring: rabbitmq: host: xx.xx.xx.xx port: 5672 virtual-host: / username: 默认guest password: 默认guest 编写生产者代码 使用@Configuration 表名它是配置类 再类中声明三要素 //交换机名称 @Bean("itemTopicExchange")

Springboot 整合RabbitMq ,用心看完这一篇就够了

Springboot 整合RabbitMq ,用心看完这一篇就够了 https://blog.csdn.net/qq_35387940/article/details/100514134包括有rabbitMq相关的一些简单理论介绍,provider消息推送实例,consumer消息消费实例,Direct.Topic.Fanout的使用,消息回调.手动确认等. (但是关于rabbitMq的安装,就不介绍了)——————————————————————————————————————————————

RabbitMq 实现延时队列-Springboot版本

rabbitmq本身没有实现延时队列,但是可以通过死信队列机制,自己实现延时队列: 原理:当队列中的消息超时成为死信后,会把消息死信重新发送到配置好的交换机中,然后分发到真实的消费队列: 步骤: 1.创建带有时限的队列 dealLineQueue; 2.创建死信Faout交换机dealLineExchange; 3.创建消费队列realQueue,并和dealLineExchange绑定 4.配置dealLineQueue 的过期时间,消息过期后的死信交换机,重发的routing-key: 以下

SpringBoot:RabbitMQ 延迟队列

SpringBoot 是为了简化 Spring 应用的创建.运行.调试.部署等一系列问题而诞生的产物,自动装配的特性让我们可以更好的关注业务本身而不是外部的XML配置,我们只需遵循规范,引入相关的依赖就可以轻易的搭建出一个 WEB 工程 初探RabbitMQ消息队列中介绍了RabbitMQ的简单用法,顺带提及了下延迟队列的作用.所谓延时消息就是指当消息被发送以后,并不想让消费者立即拿到消息,而是等待指定时间后,消费者才拿到这个消息进行消费. 延迟队列 延迟队列能做什么? 订单业务: 在电商/点餐