Springboot+RabbitMQ延迟/定时队列 定时推送消息

RabbitMQ 安装包和 rabbitmq_delayed_message_exchange插件下载 :

下载地址

使用延时队列, RabbitMQ需要安装rabbitmq_delayed_message_exchange插件.
官网下载地址

Springboot+RabbitMQ延迟/定时队列 定时推送消息_第1张图片
下载对应版本的 rabbitmq_delayed_message_exchange.
下载完成后解压 , 把解压后的ez文件放到RabbitMQ安装路径的plugins下.
然后进入sbin目录执行命令 rabbitmq-plugins enable rabbitmq_delayed_message_exchange
github插件地址

Springboot 配置文件 RabbitMQ配置

  # RabbitMQ 配置
  rabbitmq:
    host: localhost
    port: 5672
    username: guest
    password: guest
    virtual-host: /
    # 开启消息发送确认
    publisher-confirms: true
    publisher-returns: true
    listener:
      simple:
        acknowledge-mode: manual

配置工具类 RabbitConfig.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;


/**
 * @ClassName RabbitConfig
 * @Description RabbitMQ 配置类
 * @Date 2019-07-20 11:44
 * @Version 1.0.0
 **/
@Configuration
public class RabbitConfig {

    //定义延迟队列
    public static final String delay_queue = "delay_queue";
    //定义延迟交换机
    public static final String delay_exchang = "delay_exchange";
    //定义路由键
    public static final String delay_routing_key = "delay_routing_key";

    /**
     * 定义延迟队列
     * @return
     */
    @Bean
    public Queue delayQueue(){
        return new Queue(delay_queue,true);
    }

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

    /**
     * 为延迟队列绑定交换机
     * @param queue
     * @param exchange
     * @return
     */
    @Bean
    public Binding delayBinding(Queue queue, CustomExchange exchange){
        return BindingBuilder.bind(queue).to(exchange).with(delay_routing_key).noargs();
    }

}

消息提供者 RabbitProduct.java

import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;

/**
 * @ClassName RabbitProduct 
 * @Description RabbitMQ 定时消息队列 消息提供者
 * @Date 2019-07-20 11:54
 * @Version 1.0.0
 **/
@Slf4j
@Component
public class RabbitProduct {

    @Resource
    private RabbitTemplate rabbitTemplate;

    public void sendDelayMessage(Integer time,String content){
        log.info("-------------启动咨询应答超时提醒延迟队列-------------");
        this.rabbitTemplate.convertAndSend(RabbitConfig.delay_exchang,RabbitConfig.delay_routing_key,content,message -> {
                //注意这里时间可以使long,而且是设置header
                message.getMessageProperties().setHeader("x-delay",time);
                return message;
            }
        );
        log.info("-------------延迟队列{}ms后执行.-------------",time);
    }

}

消息消费者 (接收监听) RabbitConsumer.java

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

import java.io.IOException;

/**
 * @ClassName RabbitReceive
 * @Description RabbitMQ 定时消息队列 消费监听回调
 * @Date 2019-07-20 12:09
 * @Version 1.0.0
 **/
@Slf4j
@Component
@RabbitListener(queues = RabbitConfig.delay_queue) //监听此队列
public class RabbitConsultConsumer {

    /**
     * 定时消息队列消费监听回调
     * @param content 消息内容
     * @param message
     * @param channel 信道
     * @throws IOException
     */
    @RabbitHandler
    public void consultReceiveDealy(String content, Message message, Channel channel) throws IOException {
        log.info("----------------接收延迟队列消息--------------------");
        log.info("接收时间:{},接受内容:{}", DateUtils.getCurrentDate("yyyy-MM-dd HH:mm:ss",String.class), content);
        //通知 MQ 消息已被接收,可以ACK(从队列中删除)了
        channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
        try {
            log.info("=============Do Something==============");
        } catch (Exception e) {
            log.error("============消费失败,尝试消息补发再次消费!==============");
            log.error(e.getMessage());
            /**
             * basicRecover方法是进行补发操作,
             * 其中的参数如果为true是把消息退回到queue但是有可能被其它的consumer(集群)接收到,
             * 设置为false是只补发给当前的consumer
             */
            channel.basicRecover(false);
        }
    }

}

测试接口

@Resource
    private RabbitConsultProduct rabbitConsultProduct;

    @RequestMapping(value = "sendDeadLetterMSG",method = {RequestMethod.GET,RequestMethod.POST})
    public void sendDeadLetterMSG(Integer time){
        rabbitConsultProduct.sendDelayMessage(time,"延迟队列测试消息");
    }

Springboot+RabbitMQ延迟/定时队列 定时推送消息_第2张图片
在这里插入图片描述
参考文章

你可能感兴趣的:(RabbitMQ)