RabbitMQ 高级特性——死信队列

devtools/2024/10/19 14:19:59/

在这里插入图片描述

文章目录

  • 前言
  • 死信队列
    • 什么是死信
    • 常见面试题
    • 死信队列的概念:
    • 死信的来源(造成死信的原因有哪些)
    • 死信队列的应用场景

前言

前面我们学习了为消息和队列设置 TTL 过期时间,这样可以保证消息的积压,那么对于这些过期了的消息,它们都去了哪里呢?可以直接将这些消息丢弃,也可以将这些消息单独放在一个叫做 “死信队列” 这样的结构中,那么什么是死信队列呢?这篇文章将为大家介绍一下什么是死信队列。

死信队列

什么是死信

死信(Dead Letter,简称DL)指的是那些由于某些原因无法被正常消费的消息。

那么死信队列就是指存储死信的队列。当消息在一个队列中变成死信之后,它能被重新发送到另一个交换机中,这个交换机就是 DLX(Dead Letter Exchange),绑定 DLX 的队列,就称为死信队列 DLQ(Dead Letter Queue)。

在这里插入图片描述

什么样的消息最终才会变成死信呢?

  1. 消息被拒绝,并且设置这个被拒绝的消息不重新进入队列
  2. 消息过期
  3. 队列达到最大长度

如何声明死信交换机和死信队列

包含两个部分:

  • 声明正常的交换机和队列
  • 声明死信交换机和死信队列
java">public static final String NORMAL_EXCHANGE = "normal.exchange";
public static final String NORMAL_QUEUE = "normal.queue";
public static final String DL_EXCHANGE = "dl.exchange";
public static final String DL_QUEUE = "dl.queue";

声明交换机、队列以及交换机和队列的绑定关系:

java">@Configuration
public class DLconfig {@Bean("normalExchange")public DirectExchange normalExchange() {return ExchangeBuilder.directExchange(Constants.NORMAL_EXCHANGE).durable(true).build();}//将正常队列和死信交换机进行绑定,这是第一这种绑定队列和死信交换机的方法@Bean("normalQueue")public Queue normalQueue() {return QueueBuilder.durable(Constants.NORMAL_QUEUE).deadLetterExchange(Constants.DL_EXCHANGE).deadLetterRoutingKey("dl").build();}//这是正常队列和死信交换机绑定的第二种方式,将配置信息以键值对的方式传递@Bean("normalQueue1")public Queue normalQueue1() {Map<String,Object> arguments = new HashMap<>();arguments.put("x-dead-letter-exchange",Constants.DL_EXCHANGE); //绑定死信交换机arguments.put("x-dead-letter-routing-key","dl"); //设置发送给死信交换机的routing key,死信交换机会根据这个routing key将死信传递给指定的死信队列return QueueBuilder.durable(Constants.NORMAL_EXCHANGE).withArguments(arguments).build();}@Bean("normalBinding")public Binding normalBinding(@Qualifier("normalQueue") Queue queue, @Qualifier("normalExchange") DirectExchange exchange) {return BindingBuilder.bind(queue).to(exchange).with("normal");}@Bean("dlExchange")public DirectExchange dlExchange() {return ExchangeBuilder.directExchange(Constants.DL_EXCHANGE).durable(true).build();}@Bean("dlQueue")public Queue dlQueue() {return QueueBuilder.durable(Constants.DL_QUEUE).build();}@Bean("dlBinding")public Binding dlBinding(@Qualifier("dlQueue") Queue queue,@Qualifier("dlExchange") DirectExchange exchange) {return BindingBuilder.bind(queue).to(exchange).with("dl");}
}

制造死信条件:

前面说了造成死信的原因有三个:1. 消息过期 2. 消息被消费者拒绝且消息不重新进入队列 3. 队列到达最大长度之后,再进入队列的消息就会成为死信。

那么我们制造出死信,就是让队列中的消息数达到最大的长度:

java">@Bean("normalQueue")
public Queue normalQueue() {return QueueBuilder.durable(Constants.NORMAL_QUEUE).deadLetterExchange(Constants.DL_EXCHANGE).deadLetterRoutingKey("dl").maxLength(10).build();
}

然后我们的生产者一次产生 20 条消息:

java">@RequestMapping("/dl")
public String dl() {for (int i = 0; i < 20; i++) {rabbitTemplate.convertAndSend(Constants.NORMAL_EXCHANGE,"normal","rabbitmq dl" + i);}return "消息发送成功";
}

NORMAL_QUEUE 我们就先不设置消费者,然后为死信队列设置消费者,看看超出队列长度的消息是否成为了死信最终到达了死信队列:

java">@Component
public class DLListener {@RabbitListener(queues = Constants.DL_QUEUE)public void listener(Message message, Channel channel) {System.out.println("死信消费者接收到消息:" + message + channel);}
}

在这里插入图片描述
在这里插入图片描述

常见面试题

死信队列的概念:

RabbitMQ中的死信队列(Dead Letter Queue,简称DLQ)是一种特殊的队列机制,用于处理那些因为某些原因无法被正常消费的消息。这些消息在RabbitMQ中被称为“死信”。死信队列的主要目的是防止消息在系统中永久丢失,同时提供一个机制来对这些无法被消费的消息进行后续处理。

死信的来源(造成死信的原因有哪些)

  1. 消息被拒绝
  • 消费者显式拒绝:消费者可以使用RabbitMQ的basic.reject或basic.nack方法拒绝消息。如果requeue参数被设置为false,则消息不会被重新放回队列,而是会被发送到死信队列(如果配置了的话)。
    消费者超时未处理:在某些情况下,如果消费者在一定时间内未能处理消息(如因为性能问题或长时间未响应),消息也可能被视为被拒绝。
  1. 消息过期
  • 设置TTL(Time To Live):RabbitMQ允许为消息或队列设置生存时间(TTL)。如果消息在设置的TTL时间内未被消费,它将被视为过期消息,并可能被发送到死信队列(取决于队列的配置)。
  1. 队列达到最大长度
  • 队列长度限制:RabbitMQ允许为队列设置最大长度限制(可以是消息数量或消息总字节数)。当队列中的消息数量或总字节数达到此限制时,新的消息可能无法被添加到队列中。如果配置了死信队列,则某些消息(如最老的消息)可能会被丢弃或发送到死信队列。

死信队列的应用场景

  1. 错误消息的重试与恢复
    当消息因为消费者代码错误、外部系统不可用或其他暂时性问题而无法被处理时,可以将这些消息发送到死信队列。然后,可以编写专门的消费者来从死信队列中拉取消息,并根据需要进行重试或人工干预。例如,可以设置重试策略,如延迟重试、增加重试次数限制等,以减少因瞬时故障而导致的消息丢失。

  2. 异常消息的分析与监控
    死信队列中的消息通常是因为某些异常或错误而产生的。通过监控和分析这些消息,可以及时发现系统中的问题,如消费者代码中的逻辑错误、外部系统的不可用状态等。这有助于快速定位问题并采取相应的解决措施,保证系统的稳定性和可靠性。

  3. 消息过期处理
    对于设置了TTL(Time To Live)的消息,如果它们在指定的时间内未被消费,将被发送到死信队列。这可以用于处理那些需要在一定时间内得到响应但未能及时处理的消息。例如,在订单系统中,如果某个订单状态更新消息在一定时间内未被处理,可以将其发送到死信队列,并由专门的消费者进行过期处理,如取消订单、发送通知等。

  4. 消息审计与合规性检查
    在某些业务场景中,需要对消息进行审计或合规性检查。通过将无法通过审计或合规性检查的消息发送到死信队列,可以确保只有符合要求的消息被进一步处理。这有助于满足行业监管要求,保护企业利益,并避免潜在的法律风险。

  5. 消息路由与分流
    在某些复杂的消息系统中,可能需要根据消息的不同属性或处理结果将其路由到不同的队列中。通过使用死信队列作为中间环节,可以实现更灵活的消息路由和分流策略。例如,可以将无法被当前消费者处理的消息发送到死信队列,并由另一个消费者进行进一步处理或路由。

  6. 消息备份与恢复
    在某些情况下,可能需要将重要消息进行备份以防止数据丢失。通过将消息发送到死信队列(作为备份队列),可以在系统发生故障或数据丢失时进行恢复。这有助于确保数据的安全性和完整性。


http://www.ppmy.cn/devtools/127031.html

相关文章

使用Docker启动的Redis容器使用的配置文件路径等问题以及Python使用clickhouse_driver操作clickhouse数据库

一、使用Docker启动的Redis容器使用的配置文件路径等问题 1.docker启动的redis使用的配置文件路径是什么 使用docker搭建redis服务&#xff0c;本身redis启动的时候可以指定配置文件的&#xff0c; redis-server /指定配置文件路径/redis.conf。 但手上也没有一个redis配置文件…

408算法题leetcode--第37天

1049. 最后一块石头的重量 II 题目地址&#xff1a;1049. 最后一块石头的重量 II - 力扣&#xff08;LeetCode&#xff09; 题解思路&#xff1a;01背包 时间复杂度&#xff1a;O(n*m) 空间复杂度&#xff1a;O(m) 代码: class Solution { public:int lastStoneWeightII(…

Java基于SSM微信小程序物流仓库管理系统设计与实现(源码+lw+数据库+讲解等)

选题背景 随着社会的发展&#xff0c;社会的方方面面都在利用信息化时代的优势。互联网的优势和普及使得各种系统的开发成为必需。 本文以实际运用为开发背景&#xff0c;运用软件工程原理和开发方法&#xff0c;它主要是采用java语言技术和mysql数据库来完成对系统的设计。整个…

JS中Array的常用方法

文章目录 1. 创建和初始化数组2. 添加和删除元素3. 查找元素4. 遍历数组5. 数组转换6. 排序和反转7. 其他方法 JavaScript 中的 Array 对象提供了许多常用的方法&#xff0c;这些方法可以帮助你更方便地操作数组。以下是一些常用的 Array 方法及其用法&#xff1a; 1. 创建和…

【学术会议-6】激发灵感-计算机科学与技术学术会议邀您参与,共享学术盛宴,塑造明天的科技梦想!

【学术会议-6】激发灵感-计算机科学与技术学术会议邀您参与&#xff0c;共享学术盛宴&#xff0c;塑造明天的科技梦想&#xff01; 【学术会议-6】激发灵感-计算机科学与技术学术会议邀您参与&#xff0c;共享学术盛宴&#xff0c;塑造明天的科技梦想&#xff01; 文章目录 【…

Llama3-Factory模型部署新手指南

一、介绍 为了保持其公司在人工智能开源大模型领域的地位&#xff0c;社交巨头Meta推出了旗下最新开源模型。当地时间4月18日&#xff0c;Meta在官网上宣布公布了旗下最新大模型Llama 3。目前&#xff0c;Llama 3已经开放了80亿&#xff08;8B&#xff09;和700亿&#xff08;…

量子计算机的原理与物理实现

量子计算机的原理与物理实现很复杂 指导性原则 首先思考制备一台量子计算机需要些什么&#xff1f; 需要量子比特——二能级量子系统。除了量子计算机需要满足一些物理特性&#xff0c;它还必须要把量子比特绘制到某种初态上&#xff0c;以及测量系统的输出态。 而实验上的挑战…

面试22222

好的&#xff0c;我会逐步解释这些面试问题&#xff0c;并给出一些应答建议。我们先从第一个问题开始&#xff1a; 1. 介绍一下你的学术背景和工作经验&#xff0c;以及为什么对生物信息学感兴趣。 回答思路&#xff1a; 首先简单概述你的学术背景&#xff0c;比如你的专业、…