SpringBoot+RabbitMQ延时队列(插件版)
使用场景:淘宝7天自动确认收货,12306订单15分钟之内未支付等等…
1、安装地址
https://github.com/rabbitmq/rabbitmq-delayed-message-exchange/releases
2、文件放到Linux文件下
rabbitmq安装目录plugins下
我的是 /usr/lib/rabbitmq/lib/rabbitmq_server-3.7.18/plugins
3、执行命令
rabbitmq-plugins enable rabbitmq_delayed_message_exchange
4、重启rabbitmq
rabbitmqctl stop
rabbitmq-server -detached
5、启动rabbitmq
浏览器访问有选中的交换机则安装成功
6、整合SpringBoot
1、依赖
<dependencies>
<!--SpringBoot-->
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.6.4</version>
</dependency>
<!--RabbitMQ-->
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-amqp -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
<version>2.7.7</version>
</dependency>
<!--Lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.20</version>
</dependency>
</dependencies>
2、yaml
server:
port: 5672
spring:
application:
name: hotel-rabbitmq
rabbitmq:
username: admin
password: admin
host: 192.168.132.128
port: 5672
virtual-host: /
listener:
simple:
#手动确认机制
acknowledge-mode: manual
#开启true确认消息
publisher-returns: true
#消息发送到交换机上触发回调函数
publisher-confirm-type: correlated
template:
mandatory: false #延时队列路由不生效解决方法
3、配置文件
package edu.hotel.rabbitmq.config;
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.net.BindException;
import java.util.HashMap;
import java.util.Map;
@Configuration
public class RabbitMQConfig {
/**交换机名称**/
public static final String LAZY_EXCHANGE ="LazyExchange";
/**队列名称**/
public static final String LAZY_Queue ="LazyQueue";
/**routingKey*/
public static final String LAZY_KEY ="10000";
@Bean
public CustomExchange customExchange(){
Map<String, Object> map = new HashMap<>();
//设置交换机支持延迟消息推送
map.put("x-delayed-type","direct");
return new CustomExchange(LAZY_EXCHANGE,"x-delayed-message",true,false,map);
}
@Bean
public Queue LazyQueue(){
//测试设置不用持久化
return new Queue(LAZY_Queue,false);
}
@Bean
public Binding LazyBinding(){
return BindingBuilder.bind(LazyQueue()).to(customExchange()).with(LAZY_KEY).noargs();
}
}
4、生产者
package edu.hotel.rabbitmq.service.impl;
import edu.hotel.rabbitmq.service.RabbitMQService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.AmqpException;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageDeliveryMode;
import org.springframework.amqp.core.MessagePostProcessor;
import org.springframework.amqp.core.ReturnedMessage;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import java.text.SimpleDateFormat;
import java.util.Date;
@Service
@Slf4j
public class RabbitMQServiceImpl implements RabbitMQService {
@Autowired
private RabbitTemplate rabbitTemplate;
@PostConstruct
public void init(){
/**
* 消息发送到交换机成功回调函数
*/
rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback() {
@Override
public void confirm(CorrelationData correlationData, boolean b, String s) {
if (b){
log.info("消息投递到交换机成功");
}else {
log.error("消息投递到交换机失败,原因->{}",s);
}
}
});
/**交换机投递到队列失败回调函数**/
rabbitTemplate.setReturnsCallback(new RabbitTemplate.ReturnsCallback() {
@Override
public void returnedMessage(ReturnedMessage returnedMessage) {
log.error("投递到队列失败,错误原因->{}",returnedMessage.getMessage());
}
});
}
@Override
public Boolean sendLazyMessage(String value) {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
log.info("消息发送时间->{}",simpleDateFormat.format(new Date()));
rabbitTemplate.convertAndSend("LazyExchange", routinKey, value, new MessagePostProcessor() {
@Override
public Message postProcessMessage(Message message) throws AmqpException {
Integer key = Integer.parseInt(RabbitMQConfig.LAZY_KEY);
log.info("延迟时间->{}",key);
//这个底层就是setHeader("x-delay",i);是一样的 设置延时时间
message.getMessageProperties().setDelay(key);
return message;
}
});
return true;
}
}
5、发送消息
@GetMapping("/sendmessage")
public String sendMessage(){
rabbitMQService.sendLazyMessage("我是延迟消息");
return "发送成功";
}
6、消费者
/**
* 消费者
*/
@Slf4j
@Component
public class RabbitMQConsumer {
@RabbitListener(queues = "LazyQueue")
public void lazyListener(String message, Channel channel, Message message2) throws IOException, InterruptedException {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
log.info("消息接收时间->{}",simpleDateFormat.format(new Date()));
log.info("消息内容是->{}",message);
log.info("{}",message2.getMessageProperties().getDeliveryTag());
Thread.sleep(10000);
channel.basicAck(message2.getMessageProperties().getDeliveryTag(),false);
}
}