rabbitmq基础7——队列和消息过期时间设置、死信队列、延迟队列、优先级队列、回调队列、惰性队列

2023-11-13

一、过期时间

  • 这里过一个知识点——过期时间,即对消息或队列设置过期时间(TTL)。一旦消息过期,消费就无法接收到这条消息,这种情况是绝不允许存在的,所以官方就出了一个对策——死信队列,死信队列最初出现的意义就是为了应对消息过期丢失情况的手段之一。

  • 那么过期时间具体怎么设置呢?运维人员只需了解外部层面的,因为对消息设置过期时间有两个维度,一个是定义消息本身属性时开发人员在代码里加进去的一个参数(初中级运维看不到),另外一个是定义队列属性的,可以从web监控页面查看。

  • 什么是过期时间?

    • 指对消息和队列设置 过期时间,简称TTL,是Time to Live 的简称。
  • TTL设置对象和方式?

    • 针对队列设置过期时间,从队列创建开始算起,一旦达到设置的过期时间后,队列自动删除,队列里的所有消息都会被删除。在web监控中的“ x-expires ”参数,也是上一章节中咱们提到过的。
    • 针对消息设置过期时间,有两个维度:
      • 第一个是,通过队列属性设置,队列中所有消息都有相同的过期时间。在web监控中的“ x-message-ttl ”参数。
      • 第二个是,对消息本身进行单独设置,每条消息的 TTL 可以不同。此种方式只能通过代码来设置,在web监控中发送消息已不支持该种消息参数。
      • 如果两种维度一起使用,则消息的 TTL 以两者之间较小的那个数值为准。

1.1 针对队列设置

1.创建ceshi_1队列时,使用“x-expires”参数指定过期时间,单位毫秒。我这里设置的是5s后自动删除。
在这里插入图片描述
2. 创建后,会显示Exp,表示已设置过期时间。
在这里插入图片描述
3. 5s后再次查看,ceshi_1队列已自动删除。

在这里插入图片描述

1.2 针对消息设置

  • 这里演示第一种维度设置,通过对队列参数设置来控制消息过期时间。此种方式设置后,所有进入该队列的消息只能存活自定义的那个时间。
  1. 创建ceshi_2队列时,通过指定“x-message-ttl”参数设置该队列里的消息过期时间,单位毫秒。我这里设置的是5s,代表进入ceshi_2队列的所有信息都只会保留5s,之后自动删除。

在这里插入图片描述
2.ceshi_2队列创建完后同样也有个标志TTL,代表已对该队列的消息设置了过期时间。

在这里插入图片描述
3. 现在对ceshi_2队列发布消息“wuhan”。
在这里插入图片描述
在这里插入图片描述

  1. 5s时间到,消息自动删除,队列显示挤压队列为0。

在这里插入图片描述

二、死信队列

  • 咱们前面铺垫讲了一下消息的过期时间,当消息过期后消费者收不到消息,这对于公司业务来说非常严峻,所以当消息过期后,它在队列中会变成死信队列。
  • 消息变成死信的几种情况:
    • 消息被拒绝 (Basic.Reject/Basic.Nack),并且设置 requeue 参数为 false。
    • 消息过期。
    • 队列达到最大长度,即将删除一些。

2.1 死信交换器

  • 死信交换器是什么?
    • 死信交换器,英文名为Dead-Letter-Exchange,简称DLX,也有人称之为死信邮箱。当消息在一个队列中变成死信 (dead message) 之后,它能被重新被发送到另一个交换器中,这个交换器就是 DLX,绑定 DLX 的队列就称之为死信队列。
    • DLX 也是一个正常的交换器,和一般的交换器没有区别,只是在创建某个队列时指定某个交换器为死信交换器,是队列的属性配置。当这个队列中存在死信时,该死信会重新发布到设置的 DLX 上去,进而被路由到死信队列。
  1. 现在有两个正常交换器,都开启了持久化。其中qingjun_exchange交换器还没有绑定队列,baimu_exchange交换器通过baimu-baimu_key绑定键与队列baimu_queue绑定。

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

2.创建队列qingjun_queue时,通过参数“x-dead-letter-exchange”指定死信交换器,也可以通过“x-dead-letter-routing-key”指定绑定键,如果没设置绑定键,则使用死信交换器原来的绑定键。比如我这里没有指定死信交换器绑定键就还是使用原来的绑定键“baimu-baimu_key”。

在这里插入图片描述
在这里插入图片描述
3. 将队列qingjun_queue与交换器qingjun_exchange绑定,这样一来,当qingjun_queue里存在死信时,会把死信发给baimu_exchange,再到死信队列baimu_queue里。

在这里插入图片描述

2.2 死信队列原理

  • 如下图,baimu_exchange为死信交换器,baimu_queue为死信队列。

在这里插入图片描述

  1. 发一条“wuhan”消息给qingjun_queue队列。

在这里插入图片描述
2. 此时消息在qingjun_queue队列里。
在这里插入图片描述
3. 等到了过期时间后,消息从qingjun_queue队列里消失,并存在了死信baimu_queue队列里。
在这里插入图片描述
在这里插入图片描述

2.3 延迟队列(特殊用法)

  • 延迟队列并非是rabbitmq的直接功能,而是通过死信队列和过期时间配合使用演练模拟延迟队列的一种用法。
  • 什么是延迟队列?
    • 延迟队列存储的对象是对应的延迟消息,所谓“延迟消息”是指当消息被发送以后,并不想让消费者立刻拿到消息,而是等待特定时间后,消费者才能拿到这个消息进行消费。
    • 回看死信队列的工作流程,当我想拿死信队列里的消息时,这种情况下,这个死信队列也是延迟队列。为什么我会想拿死信队列里的消息呢?有以下场景可以适用。
  • 适用场景
    • 在订单系统中,一个用户下单之后通常有 30 分钟的时间进行支付,如果 30 分钟之内没有支付成功,那么这个订单将进行异常处理,这时就可以使用延迟队列来处理这些订单了。
    • 当我下班后,还在公司们口就可以通过手机远程遥控家里的空调在我上地铁后就开始制冷工作,这时就可以把我的请求指令消息放发送到设有过期时间的队列中,过期时间就是我从公司走到地铁的时间,此时消息过期发送到死信队列里,再推送到消费者空调开始制冷。这里的死信队列就可以看作延迟队列。

在这里插入图片描述

现在我有以下需求,刚下班,想一回到家就能吹到25°C制冷、自动风速模式的空调。从公司走到地铁站需要20分钟,在我达到地铁站时家里的空调开始以16°C、5级风速模式制冷,该模式下制冷时间为我地铁通勤时间10分钟,等我下地铁时再调成25°C、2级风速模式制冷,下地铁到家需要10分钟,这10分种内空调需要调成25°C、自动风速模式工作,等我回到家正好是25°C、自动风速。

  • 在公司门口就远程控制家里空调,设置三个定时工作:
    • 第一个定时是在20分钟后开始工作,这一指令是第一条消息,完全匹配到绑定键_1到达queue_1,20分钟后消息过期,到达延迟队列_1,消费者开始消费第一条消息。
    • 第二个定时是在30分钟后开始工作,这一指令是第二条消息,完全匹配到绑定键_2到达queue_2,30分钟后消息过期,到达延迟队列_2,消费者开始消费第二条消息。
    • 第三个定时就是40分钟后开始工作,这一指令是第三条消息,完全匹配到绑定键_3到达queue_3,40分钟后消息过期,到达延迟队列_3,消费者开始消费第三条消息。
  • 20分钟后,我走到地铁站,开始消费第一条消息,空调开始以16°C、5级风速制冷。
  • 地铁通勤时间10分钟,此时开始消费第二条消息,空调开始以25°C、2级风速制冷。
  • 10分钟后下地铁,第三条消息开始消费,空调调成25°C、自动风速模式。
  • 等我回到家时,空调温度正好是25°C、自动风速。

三、优先级队列

  • 通过参数 x-max-priority可以设置优先级队列和优先级消息。优先级高的队列具有高的优先权,优先级高的消息具备优先被消费的特权。
  • 适用场景
    • 业务数据大,大到经常挤压,但又要满足业务需求。
    • 优先级队列的使用需要看业务情况的,如果消费者的消费速度大于生产者的速度且 Broker 中没有消息堆积情况下,对发送的消息设置优先级就没有什么实际意义了。因为生产者刚发送完一条消息就被消费者消费了,那么就相当于 Broker 中至多只有一条消息,对于单条消息来说优先级是没有什么意义的。

3.1 监控页面创建优先级队列

  1. 创建wuhan_queue队列时添加参数x-max-priorit,就创建了优先级队列,并显示有“Pri”标识。

在这里插入图片描述

3.2 监控页面创建优先级消息

  • 消息的优先级最大不能超过队列的最大优先级,默认最低为0。
  • 优先级高的先被消费,优先级低的后被消费。
  1. 在web监控里创建消息时,可以指定消息相关参数,当前版本有效参数如下显示,其中就有个优先级的参数priority。

在这里插入图片描述
2. 创建第一条消息"beijing",优先级为10,创建第二条消息“wuhan”,优先级为4。beijing会先被消费,wuhan后被消费。

在这里插入图片描述

四、回调队列

  • 回调队列,指在RPC调用过程中需要使用的回复的队列。

4.1 RPC的定义

  • RPC,是 Remote Procedure Call 的简称,即远程过程调用。
  • 它是一种通过网络从远程计算机上请求服务,而不需要了解底层网络的技术。RPC 的主要功用是让构建分布式计算更容易在提供强大的远程调用能力时不损失本地调用的语义简洁性。
    • 打个比方,现有两台服务器A和B,一个应用部署在 A 服务器上,想要调用B服务器上应用提供的函数或方法,由于不在同一个服务器上不能直接调用,所以需要需要通过网络来表达调用的语义和传达调用的数据。
  • RPC 的协议有很多,比如CORBA、Java RMI、WebService 的 RPC 风格、Hessian、Thrift 、Restful API。

4.2 PRC工作机制

RPC工作流程

  1. RPC客户端在生产者服务器上,RPC服务端在消费者服务器上。
  2. 生产者向一个普通队列baimu_queue发送一条消息,消息内容为调用消费者服务器上的函数A,并通过reply_to参数指定消费者接收到生产者的信息并处理完后发送到哪个队列上,此队列就称之为回调队列,通过correlation_id参数设置消息唯一表示符,好让生产者识别是哪一个请求回复的消息。
    • 消息是通过底层的网络协议传递到消费者服务器上,由于网络协议是基于二进制的,内存中的参数的值要序列化成二进制的形式,也就是序列化(Serialize)或编组(marshal),通过寻址和传输将序列化的二进制发送给消费者服务器。
  3. 消费者收到消息时,进行调用函数A业务处理,业务处理完成后,将处理结果和收到消息的唯一标识符打包发送到回调队列qingjun_queue,这条消息可以称为响应消息。
    • 消费者服务器收到消息后,需要对参数进行反序列化(序列化的逆操作),恢复为内存中的表达方式,然后找到对应的方法(寻址的一部分)进行本地调用,然后得到返回值。将返回值再以序列化方式放给生产者服务器。
  4. 生产者服务器接到信息后,再反序列化,恢复为内存中的表达方式,此时才会在回调队列中显示回复信息,再然后再并根据消息唯一标识符进行处理。

在这里插入图片描述

4.3 监控页面上使用

  1. 在生产者服务器上发送消息时,指定correlation_id和reply_to参数。
    在这里插入图片描述

  2. reply_to参数指定的回到队列需要先创建好,可以是一个普通队列,只是用来接收回调消息的。这里就不多此一举了。

五、惰性队列

  • 默认情况下,当生产者将消息发送到rabbitmq时,队列中的消息会尽可能地存储在内存之中,这样可以更加快速地将消息发送给消费者。即使是持久化的消息,在被写入磁盘的同时也会在内存中驻留一份备份。当消费者由于各种各样的原因,比如消费者下线、宕机、由于维护而关闭等原因致使长时间内不能消费消息而造成堆积时,使用惰性队列就可以很好解决了。

  • 惰性队列作用

    • 惰性队列会将接收到的消息直接存入磁盘中,而在消费者消费到相应的消息时才会被加载到内存中。
    • 它的出现就是可以有效解决消费者异常时可以存储大量挤压得消息,所以惰性队列能支持更多的消息存储。
  • 惰性队列对服务器资源要求:

    • 会增加磁盘I/O读写能力。惰性队列是将消息直接存盘,不管是持久化的或者是非持久化的,这样可以减少了内存的消耗,但是会增加 I/O 的使用,如果消息是持久化的,那么这样的 I/O操作不可避免。
    • 注意如果惰性队列中存储的是非持久化的消息,内存的使用率会一直很稳定,但是重启之后消息一样会丢失。
  • 队列模式

    • 分Default 持久化模式和 Transient瞬时模式,前者队列持久化,可以保证数据的高可靠;后者数据只在内存里,服务器关闭数据消失。
    • 在高版本中,比如我这里的3.11.5版本,可以在创建队列指定“x-queue-mode”参数设置该队列为惰性队列。

5.1 监控页面上使用

  • 如下图,在创建队列test_queue时,添加参数“x-queue-mode”会默认带出“lazy”一词,代表设置为惰性队列。

在这里插入图片描述

  • 惰性队列也同样会显示一个标识“Args”。

在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

rabbitmq基础7——队列和消息过期时间设置、死信队列、延迟队列、优先级队列、回调队列、惰性队列 的相关文章

  • touch命令在一个目录下创建多个文件(不同名称)

    我想制作一个在 bash 中创建目录和文件结构的脚本 我尝试过这样的事情 mkdir p 1 2 touch 1 2 a b c a b c 应该是在一个命令或其他命令中创建的文件 但由于某种原因 结构是这样的 current folder
  • 操作系统什么时候清除进程的内存

    进程在某些操作系统上成功或异常终止 操作系统何时决定擦除分配给该进程的内存 数据 代码等 在退出时或当它想为新进程分配内存时 这个清除内存分配过程在所有操作系统 winXP Win7 linux Mac 上都相同吗 据我了解 页表具有该进程
  • 如何使用AWK脚本检查表的所有列数据类型? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 在这里 我正在检查表中第一列的数据类型 但我想知道AWK中表的所有列数据类型 我尝试过 但只能获得一列数据类型 例如 Column 1
  • 停止服务时单元陷入故障状态(状态=143)[关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 这是我的问题 我有 CentOS 和 java 进程在上面运行 Java进程是通过启动 停止脚本来操作的 它也创建了 java 实例的 p
  • 无法执行'x86_64-conda_cos6-linux-gnu-gcc':没有这样的文件或目录(pysam安装)

    我正在尝试安装 pysam 执行后 python path to pysam master setup py build 这个错误的产生是 unable to execute x86 64 conda cos6 linux gnu gcc
  • Linux 中热插拔设备时检测设备是否存在

    我正在运行 SPIcode http lxr free electrons com source drivers spi spi omap2 mcspi c在熊猫板上 我想知道其中的哪个功能code http lxr free electr
  • 如何在Python中独立于语言安装(linux)获取用户桌面路径

    我找到了 如何找到用户桌面的路径 的几个问题和答案 但在我看来它们都已失效 至少我找到的那些 原因是 如果用户安装的 Linux 不是英语 他或她的桌面很可能位于除 Desktop 例如 对于瑞典语 我相信它是在 Skrivbord 谁知道
  • Linux shell 脚本:十六进制数字到二进制字符串

    我正在 shell 脚本中寻找一些简单的方法来将十六进制数字转换为 0 和 1 字符的序列 Example 5F gt 01011111 是否有任何命令或简单的方法来完成它 或者我应该为其编写一些开关 echo ibase 16 obase
  • 如何让“grep”从文件中读取模式?

    假设有一个很大的文本文件 我只想打印与某些模式不匹配的行 显然 我可以使用egrep v patter1 pattern2 pattern3 现在 如果所有这些模式都在一个文本文件中怎么办 最好的制作方法是什么egrep从文件中读取模式 g
  • 适用于 KDE 和 Gnome 的 Gui [重复]

    这个问题在这里已经有答案了 我想为一个现在是 CLI 的应用程序编写一个 gui 它需要在 KDE 和 Gnome DE 中 看起来不错 充分利用用户的外观设置 如果我选择 Qt 或 GTK 我能够做到这一点吗 它们与两个 DE 集成良好吗
  • 无需 cron 在后台发送邮件

    我想知道是否有一种方法可以运行 PHP 循环 以便在后台向订阅者发送几百封电子邮件 我的目标是格式化新闻通讯 单击发送 然后关闭浏览器或更改页面 当然 发送电子邮件的实际过程将在后台运行 不会因浏览器关闭而中断 我知道这可以通过 cron
  • Composer 安装要求

    我正在尝试将 Composer 安装到 Laravel 项目中 当我做的时候sudo composer install在项目目录中它显示了两个错误 Problem 1 Installation request for simplesoftw
  • Linux 桌面快捷方式和安装图标

    我需要添加什么到我的 spec文件来创建桌面快捷方式并在安装过程中为快捷方式分配一个图标 rpm 如果需要脚本 一个示例将非常有帮助 您在 Linux 下使用 desktop 文件作为图标 图标放置的位置取决于您使用的发行版和桌面环境 由于
  • 在主目录中安装库

    在 Linux Ubuntu 中 我尝试运行一个工具 但它显示错误 库丢失 我无权在系统中安装任何内容 或者根本无法从我的用户帐户执行 sudo 是否可以在我的主目录 没有 sudo 中安装缺少的库 在我的例子中为 libstdc so 6
  • 生产者/消费者的不同语言

    我想知道是否可以通过 AMQP 和 RabbitMQ 对生产者和消费者使用不同的语言 例如 Java 代表生产者 python php 代表消费者 或者反之亦然 是的 AMQP 与语言无关 这意味着只要您有可以连接到 AMQP 的客户端sa
  • 将 sensu-client 连接到服务器时 AMQP 连接的 bad_header

    我已经安装了 sensu 和厨师社区食谱 但是 sensu客户端无法连接到服务器 导致rabbitmq连接错误 尝试连接时消息超时 这是详细的客户端日志 来自 sensu client log 的日志 timestamp 2014 07 0
  • Locale.getDefault() 始终返回 en

    unix 机器上的服务器始终使用 en 作为默认区域设置 以下是区域设置输出 LANG en US LC CTYPE C LC NUMERIC C LC TIME C LC COLLATE C LC MONETARY C LC MESSAG
  • 从 PL/SQL 调用 shell 脚本,但 shell 以 grid 用户而非 oracle 身份执行

    我正在尝试使用 Runtime getRuntime exec 从 Oracle 数据库内部执行 shell 脚本 在 Red Hat 5 5 上运行的 Oracle 11 2 0 4 EE CREATE OR REPLACE proced
  • awk 子串单个字符

    这是columns txt aaa bbb 3 ccc ddd 2 eee fff 1 3 3 g 3 hhh i jjj 3 kkk ll 3 mm nn oo 3 我可以找到第二列以 b 开头的行 awk if substr 2 1 1
  • 无法加载 JavaHL 库。- linux/eclipse

    在尝试安装 Subversion 插件时 当 Eclipse 启动时出现此错误 Failed to load JavaHL Library These are the errors that were encountered no libs

随机推荐