RabbitMQ 安装包和 rabbitmq_delayed_message_exchange插件下载 :
使用延时队列, RabbitMQ需要安装rabbitmq_delayed_message_exchange插件.
官网下载地址
下载对应版本的 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,"延迟队列测试消息");
}