SpringBoot整合RabbitMq实现延时队列
说明:
RabbitMq通过使用rabbitmq_delayed_message_exchange插件实现延迟消息。
它与TTL方式不同的是,TTL方式存放在死信队列(dalayqueue) 里,它是基于插件存放消息放在延时交换机里面(x-delayed-message exchange)
1. 生产者将消息(msg)和路由键(routekey)发送指定的延时交换机(exchange)上
2. 延时交换机(exchange)存储消息等待消息到期根据路由键(routekey)找到绑定自己的队列
(queue)并把消息给它
3. 队列(queue)再把消息发送给监听它的消费者(customer)
rabbitmq_delayed_message_exchange 插件安装
1.插件下载
下载地址: https://github.com/rabbitmq/rabbitmq-delayed-message-exchange/releases
2.插件安装
将插件拷贝到rabbitmq-server的安装路径: /usr/lib/rabbitmq/lib/rabbitmq_server-3.8.4/plugins
3.启用插件
rabbitmq-plugins list
rabbitmq-plugins enable rabbitmq_delayed_message_exchange
4.重启rabbit-service
systemctl restart rabbitmq-server
SpringBoot项目代码
1. pom.xml中添加RabbitMQ
<!-- MQ依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
<version>3.0.2</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>3.0.2</version>
</dependency>
2.application.yml中添加rabbitMq的配置
spring:
rabbitmq:
host: 127.0.0.1
port: 5672
username: root
password: 123456
virtual-host: /svr
3.添加RabbitConfig类
application.yml中请添加自定义的queue、exchange、delayRoutingKey
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.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.HashMap;
import java.util.Map;
@Configuration
public class RabbitConfig {
@Value("${queue.demo.delayQueue}")
private String delayQueue;
@Value("${queue.demo.delayExchange}")
private String delayExchange;
@Value("${queue.demo.delayRoutingKey}")
private String delayRoutingKey;
@Bean
public Queue queue() {
return new Queue(delayQueue, true);
}
@Bean
public CustomExchange delayExchange() {
Map<String, Object> args = new HashMap<>(16);
args.put("x-delayed-type", "direct");
return new CustomExchange(delayExchange, "x-delayed-message", true, false, args);
}
@Bean
public Binding binding(Queue queue, CustomExchange delayExchange) {
return BindingBuilder.bind(queue).to(delayExchange).with(delayRoutingKey).noargs();
}
}
4.添加消费者类监听消息处理
使用推消息模式接收延迟队列的广播
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;
@Component
public class MsgListener {
@RabbitListener(queues = {"${queue.demo.delayQueue}"})
public void msgConsumer(String msg){
System.out.println("接受到的消息:" + msg);
}
}
5.发送消息测试
1.添加自定义工具类MsgPublishService
import org.springframework.amqp.AmqpException;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessagePostProcessor;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class MsgPublishService {
@Autowired
private RabbitTemplate rabbitTemplate;
/**
* 发送延时消息
*
* @param delayExchange
* @param delayRoutingKey
* @param message
* @param delayTimes
*/
public void sendTtlMsg(String delayExchange, String delayRoutingKey, String message, long delayTimes) {
try {
rabbitTemplate.convertAndSend(delayExchange, delayRoutingKey, message, new MessagePostProcessor() {
@Override
public Message postProcessMessage(Message message) throws AmqpException {
message.getMessageProperties().setHeader("x-delay", delayTimes);
return message;
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
}
2.编写测试代码
import com.example.rabbitmqdemo.service.MsgPublishService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class DemoController {
@Autowired
private MsgPublishService msgPublishService;
@Value("${queue.delayExchange}")
private String delayExchange;
@Value("${queue.delayRoutingKey}")
private String delayRoutingKey;
@GetMapping("sendMsg")
public void pushToRabbitMq(@RequestParam("msg") String msg,@RequestParam("delayTime") Long delayTime){
msgPublishService.sendTtlMsg(delayExchange,delayRoutingKey,msg,delayTime);
}
}
测试结果
发送请求,延迟6s后消费消息
http://localhost:8080/sendMsg?msg=nihao&delayTime=6000