热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

RabbitMQ队列有Unacked消息,但无消费者信息

问题业务反馈线上队列无消费者,但是management管理端发现有Unacked量基本原理Unacked消息指的是服务端已经投递给消费者,但还没有收到消费者响应Ack这么一个中间状

问题

业务反馈线上队列无消费者,但是management管理端发现有Unacked量


基本原理

  1. Unacked消息指的是服务端已经投递给消费者,但还没有收到消费者响应Ack这么一个中间状态。
  2. 消费者假如在消费过程中(尚未给Broker响应Ack)退出,那么消费中的这部分Unacked消息会被requeue到队列,进而投递到其余消费者(假如有Consumers在线);假如没有Consumers,那这部分Unacked消息会转换为Ready状态。
  3. Unacked消息状态被Broker维护在内存中。

而上面截图的问题:队列有Unacked量,但是没有Consumers信息,似乎很矛盾。

定位

阅读服务端消费相关板块代码,发现 rabbit_queue_consumers 板块:

计算Unacked消息量

unacknowledged_message_count() -> lists:sum([queue:len(C#cr.acktags) || C <- all_ch_record()]).

读进程字典

all_ch_record() -> [C || {{ch, _}, C} <- get()].

写进程字典

store_ch_record(C = #cr{ch_pid = ChPid}) -> put({ch, ChPid}, C), ok.

rabbit_queue_consumers 板块实际是被 rabbit_amqqueue_process 调用。不难发现队列进程进程字典维护消息消费过程中的消费Channel进程等信息。

验证

  1. 启动Erlang shell

erl -name sj@test -setCOOKIE COOKIE名

  1. 获取队列amqqueue记录信息,其中包含进程pid等信息。

rpc:call(N,erlang,apply,[fun()->rabbit_amqqueue:lookup(rabbit_misc:r(<<"vhost名字">>,queue,<<"queue名字">>)) end,[]]).

  1. 获取队列进程进程字典信息。Pid为步骤2获取到的进程Pid

rpc:call(node(Pid), erlang, process_info, [Pid,dictionary]).

最终发现了相似如下6条关键信息,与问题中的Unacked量对应:

{{ch,<8232.16445.2870>}, {cr,<8232.16445.2870>,#Ref<8251.0.972816396.42542>, {[{3,<<"amq.ctag-RkzjrIA60GwE9ED8opKK7w">>}],[]}, 0, {queue,[],[],0}, {qstate,<8232.16442.2870>,dormant,{0,nil}}, 1}}

处理

已经能找到上述Unacked状态的6条消息对应的Channel进程,如何让这些消息重入队(成为Ready状态)?

阅读服务端代码,发现 rabbit_amqqueue_process 板块 handle_ch_down/2 方法,该方法内部调用 rabbit_queue_consumers 板块 erase_ch/2 方法,
最终调用 erase/2 将 {ch, ChPid} 这个key从进程字典中移除。

因而,可以通过触发channel进程DOWN

exit(ChPid,normal).

最终队列进程感知Channel进程退出,进而将Unacked状态requeue,最终消息转变为Ready状态~

拓展

如何获取队列Unacked状态消息?

sys:get_state(Pid).

有兴趣可以调试下


推荐阅读
  • 本文介绍了如何在三台CentOS 7.5虚拟机上通过Docker部署RabbitMQ集群,包括环境准备、容器创建、集群配置及故障处理等内容。 ... [详细]
  • 在使用 StackExchange.Redis 库对 Redis 集群执行 KeyRename 操作时遇到错误,原因是多键操作必须涉及单个槽位。本文将探讨如何通过哈希标签(Hash Tags)来解决这一问题。 ... [详细]
  • 详解 | 日志系统ViseLog的基本使用与功能
    本文详细介绍了日志系统ViseLog的使用方法及其核心功能,旨在帮助开发者更好地理解和利用这一工具,提高开发效率。 ... [详细]
  • 本文探讨了如何在Django中创建一个能够根据需求选择不同模板的包含标签。通过自定义逻辑,开发者可以在多个模板选项中灵活切换,以适应不同的显示需求。 ... [详细]
  • 本文详细介绍如何使用 Python 集成微信支付的三种主要方式:Native 支付、APP 支付和 JSAPI 支付。每种方式适用于不同的应用场景,如 PC 网站、移动端应用和公众号内支付等。 ... [详细]
  • 搭建Jenkins、Ant与TestNG集成环境
    本文详细介绍了如何在Ubuntu 16.04系统上配置Jenkins、Ant和TestNG的集成开发环境,涵盖从安装到配置的具体步骤,并提供了创建Windows Slave节点及项目构建的指南。 ... [详细]
  • Django 使用slug field时遇到的问题 ... [详细]
  • 本文旨在探讨如何利用决策树算法实现对男女性别的分类。通过引入信息熵和信息增益的概念,结合具体的数据集,详细介绍了决策树的构建过程,并展示了其在实际应用中的效果。 ... [详细]
  • java文本编辑器,java文本编辑器设计思路
    java文本编辑器,java文本编辑器设计思路 ... [详细]
  • 本文提供了多种方法来计算给定年份和月份的起始日和结束日,并进一步探讨了如何根据年、月、周获取特定周的起始日和结束日。 ... [详细]
  • 本文介绍了一种根据目标检测结果,从原始XML文件中提取并分析特定类别的方法。通过解析XML文件,筛选出特定类别的图像和标注信息,并保存到新的文件夹中,以便进一步分析和处理。 ... [详细]
  • 本文介绍了如何使用Java代码在Android设备上检测特定应用程序是否已安装。通过创建一个Intent并利用PackageManager查询该Intent的可用性来实现这一功能。 ... [详细]
  • 本文档详细介绍了Scrapy框架中的信号系统,包括如何利用信号来增强爬虫的功能性和灵活性,以及各个内置信号的具体用途和参数。 ... [详细]
  • addcslashes—以C语言风格使用反斜线转义字符串中的字符addslashes—使用反斜线引用字符串bin2hex—函数把包含数据的二进制字符串转换为十六进制值chop—rt ... [详细]
  • 双向数据绑定技术使得对象属性与用户界面之间可以相互影响,即对象属性的更改能即时反映到界面上,同时用户的界面操作也能同步更新对象状态。本文将介绍如何利用简单的JavaScript代码实现这一功能。 ... [详细]
author-avatar
mobiledu2502858037
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有