logo科技微讯

腾讯云消息队列 CMQ 可见消息、延迟消息计数不准确的问题

作者:科技微讯
日期:2022-12-30
📝 笔记

2023-03-29 更新:标题所反映的问题已经修复,现在:1、往队列发送了延迟消息后,消费者连接过一次后(包括连接后断开),DelayMsgNum 就能正确显示,而不是始终显示为 0,也不会被统计进 ActiveMsgNum;2、从队列中取出一条消息但一直不消费,即一直不删除,如果消息隐藏时间比较长,假设为 5min,那大概延迟 2min 后(不是官方说的 30s-60s),InactiveMsgNum 会正确显示,而不是一直显示为 0,同时 ActiveMsgNu 会相应减少。

以下是本笔记的原文。

使用 tencentcloud-sdk-nodejs-tdmqDescribeCmqQueueDetail 接口查询一个 CMQ 队列的详情,会返回 ActiveMsgNum、InactiveMsgNum、DelayMsgNum 等数据,根据文档,这三个数据的意思分别是:

  • ActiveMsgNum:在队列中处于 Active 状态(不处于被消费状态)的消息总数,为近似值。注意:此字段可能返回 null,表示取不到有效值。
  • InactiveMsgNum:在队列中处于 Inactive 状态(正处于被消费状态)的消息总数,为近似值。 注意:此字段可能返回 null,表示取不到有效值。
  • DelayMsgNum:延迟消息数。 注意:此字段可能返回 null,表示取不到有效值。

在 CMQ 后台也有对可见消息、不可见消息、堆积消息的解释:

  • 可见消息:普通消息(非延时消息)被发送到普通消息队列时, 初始状态为可见。被取走后且超过隐藏时长时间后消息还未被删除,消息会重新变成可见状态。此处显示的数据刷新会有 30s 到 60s 延迟。
  • 不可见消息:不可见消息过多一般是客户端未及时 ACK 导致的,产生不可见消息会消耗一定的内存,因此为每个队列设置了一定的容量上限。
  • 堆积消息:消息堆积一般是生产速率大于消费速率或者消费出现阻塞导致的,产生堆积会消耗一定的磁盘存储,因此为每个队列设置了一定的容量上限。

综合以上两处说明,以下是我的理解:

  • ActiveMsgNum:可以立即被消费的消息,不包括延迟消息,也不包括正在被消费的消息;
  • InactiveMsgNum:仅指正在被消费的消息,所谓正在被消费,是指取出了,并且还没被删除,并且还没超过消息隐藏时长的消息,所以它不包括延迟消息;
  • DelayMsgNum:仅指被延迟的消息,不包括可见消息,也不包括不可见消息;

但实际表现却和理论不一样,使用 DescribeCmqQueueDetail 接口查询一个队列的详情,给出来的数据和实际可能有较大误差,具体体现在:

  • 从队列中取出消息但一直不删除,ActiveMsgNum 应该减少,InactiveMsgNum 应该增加,但实际情况是它们都保持不变,虽然文档说 ActiveMsgNum 可能会延迟 30-60s 才更新,但我等了将近 10 分钟了还不更新。这就导致了 ActiveMsgNum 虽然大于 0,但从队列中查询消息可能会返回 '(10200)no message'
  • 往队列中发布 n 条延迟消息,但 n 总是被算入 ActiveMsgNum,而不是算入 DelayMsgNum,只有当消费者把队列中所有真正的可见消息全部消费完毕,接着再获取消息,这时,CMQ 才会意识到剩下的消息属于延迟消息,于是才会更新 DelayMsgNum 的数量。

总结一下:

  • ActiveMsgNum:经常大于实际值,因为它可能包括了 InactiveMsgNum 和 DelayMsgNum,虽然文档说都不包括;
  • InactiveMsgNum:我把 VisibilityTimeout 设置为 10 分钟,取出 n 条消息后 10 分钟内不删除,InactiveMsgNum 却一直保持为零,而不是 n;
  • DelayMsgNum:延迟消息的计数默认被计入 ActiveMsgNum,只有当真正的可见消息都被消费完毕,延迟消息计数才会从 ActiveMsgNum 转移到 DelayMsgNum;

BTW,tencentcloud-sdk-nodejs-tdmq 还有一个 DescribeCmqQueues 接口,它可查询全量队列的信息,但它返回的可见消息数、延迟消息数比 DescribeCmqQueueDetail 更不准确,DelayMsgNum 永远是 null。

补充

咨询了腾讯云客服:

  • DelayMsgNum:如果无消费者在线,则延时消息总数会统计为 0,当消费者连接过后(包括连接后断开),延迟消息计数才会显示正确,但事实上也不是,连接过后还是不会显示真实数据,只有当真实的可见消息都消费完毕后,延迟消息数才会从 ActiveMsgNum 计入 DelayMsgNum;
  • InactiveMsgNum:CMQ 后台监控数据显示正确,但 DescribeCmqQueueDetail 给出的数据始终为 0,这是 bug,后续会修复,这个 bug 据我观察至少在 2022/11 上旬就出现了。

相关文章:

donation赞赏
thumbsup0
thumbsdown0
暂无评论