选择
延迟队列的实现有3种方法:
- 队列设置TTL :不够灵活,每增加一个TTL时间,都要新增一条队列
- 消息设置TTL :消息入队后,遵循先进先出,TTL长的仍然比TTL短的先消费
- 基于插件实现: 消息通过自定义交换机后,不会立即分发到队列,而且存储到mnesia(分布式数据系统)表中,
达到投递时间(TTL),就投递到目标队列
所以:选择基于插件实现延迟队列
安装
下载:rabbit_delayed_message_exchange插件,解压到RabbitMQ/plugins目录
使用命令 rabbitmq-plugins enable rabbitmq_delayed_message_exchange
激活使用
流程图
实现步骤
声明配置
spring:
rabbitmq:
host: 127.0.0.1
port: 5672
username: guest
password: guest
声明队列,交换机,绑定关系
@Configuration
public class DelayQueueConfig {
public static final String DELAYED_EXCHANGE_NAME = "delayed.exchange";
public static final String DELAYED_QUEUE_NAME = "delayed.queue";
public static final String DELAYED_ROUTING_KEY = "delayed.routingkey";
//声明队列
@Bean
public Queue delayedQueue(){
return new Queue(DELAYED_QUEUE_NAME);
}
//声明一个延迟交换机
@Bean("delayedExchange")
public CustomExchange delayExchange(){
//自定义交换机类型
HashMap<String, Object> map = new HashMap<>();
map.put("x-delayed-type","direct");
/**
* 1.交换机名称
* 2.交换机类型
* 3.是否需要持久化
* 4.是否需要自动删除
* 5.其他参数
*/
return new CustomExchange(DELAYED_EXCHANGE_NAME,"x-delayed-message",true,false,map);
}
//绑定队列和延迟交换机
@Bean
public Binding bingQueueToExchange(@Qualifier("delayedQueue") Queue queue,
@Qualifier("delayedExchange") CustomExchange customExchange){
return BindingBuilder.bind(queue).to(customExchange).with(DELAYED_ROUTING_KEY).noargs();
}
}
声明生产者
@Slf4j
@RequestMapping("ttl")
@RestController
public class Producer {
public static final String DELAYED_EXCHANGE_NAME = "delayed.exchange";
public static final String DELAYED_ROUTING_KEY = "delayed.routingkey";
@Autowired
private RabbitTemplate rabbitTemplate;
//基于插件实现的延迟队列
@GetMapping("/sendDelayMsg/{msg}/{delayTime}")
public void sendMag(@PathVariable String msg,@PathVariable Integer delayTime){
rabbitTemplate.convertAndSend(DELAYED_EXCHANGE_NAME,DELAYED_ROUTING_KEY,msg, correlationDate ->{
correlationDate.getMessageProperties().setDelay(delayTime);
return correlationDate;
});
log.info("当前时间:{},延迟为:{},发送消息内容为:{}",new Date(),delayTime,msg);
}
}
声明消费者
@Slf4j
@Component
public class Consumer {
public static final String DELAYED_QUEUE_NAME = "delayed.queue";
//基础插件实现的延迟队列消费者
@RabbitListener(queues = DELAYED_QUEUE_NAME)
public void receiveQueue(Message message){
String msg = new String(message.getBody());
log.info("当前时间:{},收到消息内容为:{}",new Date().toString(),msg);
}
}
启动测试
- 浏览器中依次请求:
http://localhost:8080/ttl/sendDelayMsg/你爱我,我爱你/20000
http://localhost:8080/ttl/sendDelayMsg/你爱我,我爱你,爱情甜蜜蜜/2000