介绍
:::tips 一个队列中的消息如果超时未消费,则会变为死信,超时分为两种情况:
- 消息所在的队列设置了超时时间
- 消息本身设置了超时时间
因此我们可以通过死信交换机+ttl来实现延时消息:
- 给队列设置ttl属性,进入队列后超过ttl时间的消息变为死信
- QueueBuilder.ttl(10000)
- 给消息设置ttl属性,队列接收到消息超过ttl时间后变为死信【推荐】
- MessageBuilder.setExpiration(“10000”)
当队列、消息都设置了ttl时,任意一个到期,消息都会成为死信 :::
定义消费者
:::tips 在消息消费者中的RabbitMqListener类中定义一个消费者,并声明绑定死信交换机和死信队列 :::
//将这个类注册到Spring容器中
@Component
public class RabbitMqListener{
//声明并绑定死信交换机和死信队列,同时监听死信队列中的消息
@RabbitListener(bindings = @QueueBinding(
value = @Queue(name = "dl.ttl.queue"),
exchange = @Exchange(name = "dl.ttl.exchange"),
key = "dl"
))
public void listen(String msg){
System.out.println("接收到延迟消息:", msg);
}
}
声明ttl队列(不推荐)
:::tips 在消息消费者的配置类中声明ttl队列与交换机,并声明绑定队列和交换机 :::
@Configuration
public class XxxConfig{
//声明交换机
@Bean
public DirectExchange ttlExchange(){
return new DirectExchange("ttl.direct");
}
//声明ttl队列
@Bean
public Queue ttlQueue(){
return QueueBuilder.durable("ttl.queue") //指定队列名称
.ttl(10000) //设置队列的超时时间,单位:毫秒
.deadLetterExchange("dl.ttl.direct") //指定消息超时变成死信后发送给哪个死信交换机
.deadLetterRoutingKey("dl") //指定死信交换机的路由key
.build();
}
//声明绑定TTL队列和交换机
@Bean
public Binding ttlBinding(Queue ttlQueue, DirectExchange ttlExchange){
return BindingBuilder.bind(ttlQueue).to(ttlExchange).with("ttl");
}
}
发送ttl消息(推荐)
:::tips 在消息生产者发送消息时设置ttl超时时间 :::
@SpringBootTest
public class MyTest{
//注入RabbitTemplate对象
@Autowired
private RabbitTemplate rabbitTemplate;
@Test
public void test(){
//指定交换机名称
String exchangeName = "ttl.direct";
//指定路由key
String routingKey = "ttl";
//构建消息
Message message = MessageBuilder
.withBody("这是一条测试消息".getBytes(StandardCharsets.UTF_8))
.setDeliveryMode(MessageDeliveryMode.PERSISTENT) //设置消息持久化
.setExpiration("5000") //设置消息超时时间,单位:毫秒
.build();
// 发送消息
rabbitTemplate.convertAndSend(exchangeName, routingKey, message);
}
}