死信队列
1.死信
先从概念解释上搞清楚这个定义,死信,顾名思义就是无法被消费的消息,字面意思可以这样理解,
一般来说,producer将消息投递到broker或者直接到queue里了, consumer 从queue取出消息进行消费,
但某些时候由于特定的原因导致queue中的某些消息无法被消费,这样的消息如果没有后续的处理,就变成了死信,有死信自然就有了死信队列。
应用场景:为了保证订单业务的消息数据不丢失,需要使用到RabbitMQ的死信队列机制,
当消息消费发生异常时,将消息投入死信队列中.
还有比如说:用户在商城下单成功并点击去支付后在指定时间未支付时自动失效
2.死信来源
- 消息TTL过期
- 队列达到最大长度(队列满了,无法再添加数据到mq中)
- 消息被拒绝(basic.reject或basic.nack)并且requeue = false.
3.死信流程
4.死信队列实现
4.1 TTL过期
- 生产者
public static void main(String[] args) throws Exception {
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("127.0.0.1");
factory.setUsername("guest");
factory.setPassword("guest");
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();
channel.exchangeDeclare("logs", "fanout");
//死信消息 设置ttl时间
AMQP.BasicProperties properties =
new AMQP.BasicProperties()
.builder().expiration("10000").build();
for(int i=0;i<11;i++){
String message = i + "";
channel.basicPublish("normal_exchange","zhangsan",null,message.getBytes(StandardCharsets.UTF_8));
}
}
- 消费者1
public static void main(String[] args) throws Exception {
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("127.0.0.1");
factory.setUsername("guest");
factory.setPassword("guest");
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();
//生明交换机
channel.exchangeDeclare("normal_exchange", "direct");
channel.exchangeDeclare("dead_exchange", "direct");
//声明普通队列
Map<String, Object> arg = new HashMap<>();
//过期时间
// arg.put("x-message-ttl",10000);
//正常队列设置死信交换机
arg.put("x-dead-letter-exchange","dead_exchange");
//设置死信RoutineKey
arg.put("x-dead-letter-routing-key","lisi");
//声明队列
channel.queueDeclare("normal_queue", false,false,false,arg);
//死信队列
channel.queueDeclare("dead_queue", false,false,false,null);
//绑定交换机和队列
channel.queueBind("normal_queue", "normal_exchange", "zhangsan");
channel.queueBind("dead_queue", "dead_exchange", "lisi");
//消息拒绝
DeliverCallback deliverCallback = (counsumerTag , message) -> {
System.out.println(new String(message.getBody()));
};
CancelCallback cancelCallback = counsumerTag -> {
System.out.println("消息被中断");
};
channel.basicConsume("normal_queue", true, deliverCallback,cancelCallback);
}
- 消费者2
public static void main(String[] args) throws Exception {
ConnectionFactory factory = new ConnectionFactory();
factory.setHost("127.0.0.1");
factory.setUsername("guest");
factory.setPassword("guest");
Connection connection = factory.newConnection();
Channel channel = connection.createChannel();
DeliverCallback deliverCallback = (counsumerTag , message) -> {
System.out.println(new String(message.getBody()));
};
CancelCallback cancelCallback = counsumerTag -> {
System.out.println("消息被中断");
};
channel.basicConsume("dead_queue", true, deliverCallback,cancelCallback);
}
4.2 最大长度
- 生产者注释掉TTL相关部分
- 消费者加入
//设置队列长度限制
arg.put("x-max-length", 6);
4.3 消息被拒绝
- 消费者加入
//消息拒绝
DeliverCallback deliverCallback = (counsumerTag , message) -> {
String msg = new String(message.getBody(), "UTF-8");
if(msg.equals("3")){
System.out.println("拒绝" + msg);
channel.basicReject(message.getEnvelope().getDeliveryTag(), false);
} else {
System.out.println(new String(message.getBody()));
channel.basicAck(message.getEnvelope().getDeliveryTag(), false);
}
};
//开启手动应答
channel.basicConsume("normal_queue", false, deliverCallback,cancelCallback);
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律