本章内容
- rabbitmq如何整合springboot?
- 插件延迟方案
springboot整合rabbitmq
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.amqp</groupId>
<artifactId>spring-rabbit-test</artifactId>
<scope>test</scope>
</dependency>
server:
port: 8080
spring:
rabbitmq:
host: 127.0.0.1
port: 5672
password: 123456
username: zhazha
virtual-host: / # 虚拟主机
virtual-host本质是根据用户账户分隔出不同的虚拟机, 这样实现各个虚拟机数据的隔离, 但是这种虚拟主机可能共用同一个物理组件, 比如虚拟主机A和虚拟主机B可能共享相同的物理主机上的exchange和queue, 但是在共享的基础上却能做到数据分隔, 这是virtual-host的热点特性
通过延迟插件实现延迟队列
大体步骤
- 下载插件
- 复制到rabbitmq插件目录
- 执行命令
- 使用
下载插件
先去rabbitmq github 官方地址: github.com/rabbitmq/ra…
去下载合适的插件
我下载的是这个版本: github.com/rabbitmq/ra…
复制到rabbitmq
找到rabbitmq的plugins文件夹
将插件复制进去
执行命令
rabbitmq-plugins.bat enable rabbitmq_delayed_message_exchange
使用下面命令可以查看rabbitmq开启了几个插件
rabbitmq_server-3.11.13\sbin>rabbitmq-plugins.bat list | findstr delay
[E ] rabbitmq_delayed_message_exchange 3.11.1
怎么用?
核心在于:
public static final String DELAY_EXCHANGE_TYPE = "x-delayed-message";
public static final String DELAY_DELAY_TYPE = "x-delayed-type";
@Bean
public CustomExchange dlxExchange() {
HashMap<String, Object> arguments = new HashMap<>();
arguments.put(DELAY_DELAY_TYPE, "direct");
return new CustomExchange(DELAY_EXCHANGE, DELAY_EXCHANGE_TYPE,
true, true, arguments);
}
"x-delayed-message"和"x-delayed-type"
其它代码都一样除了 Binding Bean 代码:
@Bean
public Binding dlxBinding() {
return BindingBuilder.bind(dlxQueue()).to(dlxExchange()).with("").noargs();
}
消费者完整代码:
@Configuration
public class RabbitConsumerConfig {
public static final String DELAY_QUEUE = "delay_queue";
public static final String DELAY_EXCHANGE = "delay_exchange";
public static final String DELAY_EXCHANGE_TYPE = "x-delayed-message";
public static final String DELAY_DELAY_TYPE = "x-delayed-type";
@Bean
public CustomExchange dlxExchange() {
HashMap<String, Object> arguments = new HashMap<>();
arguments.put(DELAY_DELAY_TYPE, "direct");
return new CustomExchange(DELAY_EXCHANGE, DELAY_EXCHANGE_TYPE,
true, true, arguments);
}
@Bean
public Queue dlxQueue() {
return QueueBuilder.durable(DELAY_QUEUE)
.autoDelete()
.build();
}
@Bean
public Binding dlxBinding() {
return BindingBuilder.bind(dlxQueue()).to(dlxExchange()).with("").noargs();
}
}
@Slf4j
@Component
public class ConsumerListener {
@RabbitListener(queues = {RabbitConsumerConfig.DELAY_QUEUE})
public void messageHandler(Message message, Channel channel) throws IOException {
System.err.println("message: " + new String(message.getBody(), Charset.defaultCharset()));
log.info("收到消息的时间: " + DatePattern.NORM_DATETIME_FORMAT.format(new Date()));
channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
}
}
问: 那延迟时间怎么定义?
答: 消费者自定义延迟时间, 因为此时在 queue 上定义 消息过期时间 失效
消息队列TTL的失效
随后记录到的时间:
发送消息时间 2023-04-22 09:03:55
收到消息的时间: 2023-04-22 09:03:55 内容: hehe
说明延迟队列对消息的过期时间配置失效
那没办法只能在消费者定义过期时间了
生产者TTL配置
@GetMapping("send/{message}")
public String sendMsg(@PathVariable(name = "message") String message) {
rabbitTemplate.convertAndSend(DELAY_EXCHANGE, "", message,
msg1 -> {
msg1.getMessageProperties().setDelay(3000);
return msg1;
});
return "success";
}
消费者完成代码:
@Slf4j
public class MyMessagePostProcessor implements MessagePostProcessor {
private final String headerName;
private final String headerValue;
private final Integer delayTime;
public MyMessagePostProcessor(String headerName, String headerValue, Integer delayTime) {
this.headerName = headerName;
this.headerValue = headerValue;
this.delayTime = delayTime;
}
@Override
public Message postProcessMessage(Message message) throws AmqpException {
MessageProperties messageProperties = message.getMessageProperties();
messageProperties.setHeader(headerName, headerValue);
MessageProperties properties = message.getMessageProperties();
properties.setDeliveryMode(MessageDeliveryMode.PERSISTENT);
properties.setContentEncoding("UTF-8");
if (delayTime != null) {
properties.setDelay(delayTime);
}
log.info("发送消息时间 {}",
DatePattern.NORM_DATETIME_FORMAT.format(new Date()));
return message;
}
}
@RestController
@Slf4j
public class RabbitmqController {
public static final String DELAY_EXCHANGE = "delay_exchange";
@Resource
private AmqpTemplate rabbitTemplate;
@GetMapping("sendDelayMsg/{message}/{delayTime}")
public void sendMessage(@PathVariable("message") String message,
@PathVariable(name = "delayTime", required = false) Integer delayTime) {
rabbitTemplate.convertAndSend(DELAY_EXCHANGE, "", message,
new MyMessagePostProcessor("prefix", "suffix", delayTime));
}
@GetMapping("send/{message}")
public String sendMsg(@PathVariable(name = "message") String message) {
rabbitTemplate.convertAndSend(DELAY_EXCHANGE, "", message,
msg1 -> {
msg1.getMessageProperties().setDelay(3000);
return msg1;
});
return "success";
}
}