1、 延迟交换机主要帮我们解决什么问题?
之前我们关于消息设置过期时间都是在消息本身以及队列的维度上来进行设置,这两个维度都在不同程度上有一些问题
问题一:当我们的业务比较复杂的时候, 需要针对不同的业务消息类型设置不同的过期时间策略, name必然我们也需要为不同的队列消息的过期时间创建很多的Queue的Bean对象, 当业务复杂到一定程度时, 这种方式维护成本过高;
问题二:就是队列的先进先出原则导致的问题,当先进入队列的消息的过期时间比后进入消息中的过期时间长的时候,消息是串行被消费的,所以必然是等到先进入队列的消息的过期时间结束, 后进入队列的消息的过期时间才会被监听,然而实际上这个消息早就过期了,这就导致了本来过期时间为3秒的消息,实际上过了13秒才会被处理,这在实际应用场景中肯定是不被允许的;
延迟交换机插件可以在一定程度上解决上述两种问题。
2、 延迟交换机插件的下载安装
2.1、延迟交换机插件下载地址
rabbitMQ插件下载地址:http://rabbitmq.com/community-plugins.html
2.2、下载延迟交换机
wget https://github.com/rabbitmq/rabbitmq-delayed-message-exchange/releases/download/3.8.9/rabbitmq_delayed_message_exchange-3.8.9-0199d11c.ez
2.3、复制到docker容器中rabbitMQ的安装目录下的插件目录中
docker cp rabbitmq_delayed_message_exchange-3.8.9-0199d11c.ez rabbitmq:/opt/rabbitmq/plugins
2.4进入到rabbitMQ容器内部,启用延迟交换机插件
docker exec -it rabbitmq /bin/bash
cd /opt/rabbitmq/sbin
./rabbitmq-plugins enable rabbitmq_delayed_message_exchange
2.5 重启rabbitmq容器,更新配置
docker restart rabbitmq
3、 延迟交换机使用演示代码
3.1 配置类
package com.kkarma.config;
import com.rabbitmq.client.AMQP;
import org.springframework.amqp.core.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.HashMap;
import java.util.Map;
@Configuration
public class DelayExchangeConfig {
public static final String DELAY_EXCAHNGE_NAME = "delay-exchange";
public static final String DELAY_QUEUE_NAME = "delay-queue";
public static final String DELAY_ROUTING_KEY = "delayed.#";
@Bean
public Exchange delayExchange(){
Map<String, Object> arguments = new HashMap<>();
arguments.put("x-delayed-type", "topic");
Exchange exchange = new CustomExchange(
DELAY_EXCAHNGE_NAME,
"x-delayed-message",
true,
false,
arguments
);
return exchange;
}
@Bean
public Queue delayQueue() {
return QueueBuilder.durable(DELAY_QUEUE_NAME).build();
}
@Bean
public Binding delayBinding(Queue delayQueue, Exchange delayExchange) {
return BindingBuilder.bind(delayQueue).to(delayExchange).with(DELAY_ROUTING_KEY).noargs();
}
}
3.2 生产者端测试demo
package com.kkarma.delay;
import com.kkarma.config.DelayExchangeConfig;
import org.junit.jupiter.api.Test;
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.boot.test.context.SpringBootTest;
@SpringBootTest
public class Publisher {
private final RabbitTemplate rabbitTemplate;
@Autowired
public Publisher(RabbitTemplate rabbitTemplate){
this.rabbitTemplate = rabbitTemplate;
}
@Test
public void push(){
MessagePostProcessor processor = new MessagePostProcessor() {
@Override
public Message postProcessMessage(Message message) throws AmqpException {
message.getMessageProperties().setDelay(3000);
return message;
}
};
rabbitTemplate.convertAndSend(
DelayExchangeConfig.DELAY_EXCAHNGE_NAME,
"delayed.demo",
"往延迟队列中添加的消息",
processor
);
System.out.println("message send success");
}
}
3、 延迟交换机的缺点
延迟交换机主要是变更了消息存储的维度到交换机,加入现在我们的消息正在交换机中存储,但是还未路由到延迟队列,一旦服务宕机,延迟交换机中存储的消息直接就丢失了。这种适用于对于数据少量丢失容忍性比较强的业务场景。