实际应用中,我们都会按照时间段划分等级,例如为5 秒、30 秒、5 分钟、30 分钟、1 小时。。。。。。如下图,我们只画了三个队列,中间的时间省略了。生产者发消息时携带有时间标识的路由键,然后交换机将消息路由到对应的消息过期时间的队列上,这些队列分别绑定了死信交换机,这些死信交换机又分别绑定了死信队列,消息过期后就通过死信交换机路由到了死信队列上面,然后我们的消费者就可以监听消费死信队列上面的消息了。
注意:下面图示中多个死信交换机分别绑定了队列,这样是为了更好的区分不同时间的消息,方便处理、查看、统计、监控等,当然也可以多个死信交换机绑定同一个队列。
package com.wfg.ttl;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.MessageProperties;
import com.wfg.util.MQUtils;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
/**
* @author wufagang
* @description
* @date 2021年05月23日 5:08 下午
*/
public class Produce {
public static void main(String[] args) throws Exception {
Channel channel = MQUtils.getChannel();
//声明一个交换机,做死信交换机用
channel.exchangeDeclare("delay_exchange_5s", "direct", true, false, null);
//声明一个队列,做死信队列用
channel.queueDeclare("delay_queue_5s", true, false, false, null);
//队列绑定到交换机上
channel.queueBind("delay_queue_5s", "delay_exchange_5s", "q5s");
channel.exchangeDeclare("work_exchange", "direct", true, false, null);
Map<String, Object> arguments=new HashMap<String, Object>();
arguments.put("x-message-ttl" , 5000);//设置消息有效期1秒,过期后变成私信消息,然后进入DLX
arguments.put("x-dead-letter-exchange" , "delay_exchange_5s");//设置DLX
//为队列normal_queue 添加DLX
channel.queueDeclare("work_queue_5s", true, false, false, arguments);
channel.queueBind("work_queue_5s", "work_exchange", "q5s");
String message = LocalDateTime.now() +",延迟五秒的消息";
channel.basicPublish("work_exchange", "q5s", MessageProperties.PERSISTENT_TEXT_PLAIN, message.getBytes());
System.out.println("发送消:"+message);
channel.close();
}
}
package com.wfg.ttl;
import com.rabbitmq.client.*;
import com.wfg.util.MQUtils;
import java.io.IOException;
import java.time.LocalDateTime;
/**
* @author wufagang
* @description
* @date 2021年05月23日 5:07 下午
*/
public class Constomer {
public static void main(String[] args) throws Exception {
final Channel channel = MQUtils.getChannel();
channel.exchangeDeclare("delay_exchange_5s", "direct", true, false, null);
channel.queueDeclare("delay_queue_5s", true, false, false, null);
channel.queueBind("delay_queue_5s", "delay_exchange_5s", "q5s");
// 指该消费者在接收到队列里的消息但没有返回确认结果之前,它不会将新的消息分发给它。
channel.basicQos(1);
Consumer consumer = new DefaultConsumer(channel) {
@Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body)
throws IOException {
System.out.println("消费者收到消息:" + new String(body)+",当前时间:"+ LocalDateTime.now());
// 消费者手动发送ack应答
channel.basicAck(envelope.getDeliveryTag(), false);
}
};
System.out.println("消费延迟5秒队列中的消息======================");
// 监听队列
channel.basicConsume("delay_queue_5s", false, consumer);
}
}