第一种方式:利用两个特性:Time to Live(TTL)、Dead Letter Exchanges(DLX) {A队列过期- > 转发 给B队列}
也就是用的死信队列
我直接使用代码及输出结果来演示了
1.先把死信队列、死信交换机、 普通队列都定义出来,交换机与队列之间的关系绑定在代码中也是有注释说明
( ̄(工) ̄)代码如下:
import org.springframework.amqp.core.*;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class QueueDLX {
//死信队列
public static final String QUEUEDLX_NAME = "queuedlx_name";
//死信交换机
public static final String EXCHANGEDLX_NAME = "exchangedlx_name";
//普通队列
public static final String QUEUE_NAME = "queue_name";
//死信队列绑定死信交换机
@Bean(QUEUEDLX_NAME)
public Queue queueDLX() {
return QueueBuilder.durable(QUEUEDLX_NAME)
//这里是死信队列的特有特性,
// 具有该特性才可以进行转发给交换机
.withArgument("x-dead-letter-exchange", EXCHANGEDLX_NAME)
.withArgument("x-dead-letter-routing-key", EXCHANGEDLX_NAME).build();
}
//死信交换机
@Bean(EXCHANGEDLX_NAME)
public DirectExchange EXCHANGEDLX_NAME(){
return new DirectExchange(EXCHANGEDLX_NAME);
}
//普通队列
@Bean(QUEUE_NAME)
public Queue QUEUE_NAME(){
return new Queue(QUEUE_NAME,true);
}
//死信交换机绑定普通队列
@Bean
public Binding bindingDLX(
@Qualifier(EXCHANGEDLX_NAME) DirectExchange directExchange,
@Qualifier(QUEUE_NAME)Queue queue){
return BindingBuilder.bind(queue).to(directExchange).with(EXCHANGEDLX_NAME);
}
}
2.服务启动后会去管理页面可以看到都成功注册好了
交换机
队列
3.发送者进行测试发送消息,并指定死亡时间
( ̄(工) ̄)代码如下:
@Autowired
private RabbitTemplate rabbitTemplate;
/**
* 测试死信消息
*/
@Test
public void sendTTLDLX(){
System.out.println(new Date());
String str = "{'id' :'2'}";
//发送消息给死信队列
rabbitTemplate.convertAndSend(QueueDLX.QUEUEDLX_NAME, str.getBytes(), new
MessagePostProcessor() {
@Override
public Message postProcessMessage(Message message) throws AmqpException {
//存活时间 毫秒 2分钟
message.getMessageProperties().setExpiration("1000");
return message;
}
});
}
4.消费者监听消息队列
( ̄(工) ̄)代码如下:
/**
* 监听消息(死信消息)
* @param msg
*/
@RabbitListener(queues = {QueueDLX.QUEUE_NAME})
public void listener(@Payload Object msg) throws UnsupportedEncodingException {
Message message = (Message) msg;
String str = new String(message.getBody(),"utf-8");
System.out.println("收到死信队列的消息:"+new Date());
System.out.println(str);
}
下面我们进行测试:
5.发送id为1的消息,死亡时间为2分钟
6.发送id为2的消息,死亡时间为1秒
7.打开管理页面可以看到,两条消息都在死信队列中
8.查看消费者监听到的消息顺序
总结:使用死信队列这种方式是可以实现延迟发送消息的,但是由于消息是发送给了死信队列,那么队列的特点是什么? 先进先出,现在问题来了,先发的消息死亡时间如果比较长, 而后发的消息死亡时间比较短,即便后发的消息已经到达了死亡时间,也还是需要等待先发的那条消息到达死亡时间出去后, 后发 的这条消息才能出去队列,这就存在问题了。 可以使用 延迟插件实现 - 延迟队列(Delay Queue)模式,详情看下一篇文章!!!
配合一张图理解总结的这段话: