具有多个消费者但只有一个活动的 MQ 队列

Posted

技术标签:

【中文标题】具有多个消费者但只有一个活动的 MQ 队列【英文标题】:MQ Queue with multiple consumers but only one active 【发布时间】:2013-09-24 03:36:29 【问题描述】:

我们有一个 MQ 队列,它从我们无法控制的外部系统接收消息。 我们处理传入消息的系统至关重要,无论如何都需要启动并运行 27x7。

处理传入消息的顺序也是不可协商的,这意味着我们需要完全按照它们到达的顺序来处理它们。

为确保我们的系统 100% 可用,我们将系统部署到了一组能够处理这些消息的物理机器上。

一旦消息到达我们的系统,我们就会设置一种机制来确保消息处理不会出现故障,同时还可以通过并行处理获得一些性能提升。对我们来说,性能提升是一件好事,但它只是一个副作用,因为我们的主要目标是高可用性,同时确保正确的处理顺序。

我的想法是在每台机器上都有一个 MDB 能够处理传入的消息,但一次只有一个活跃的消费者。

我们使用 Webshere MQ 作为 JMS 提供者和 Webshere Application Server 8.5 来部署我们的应用程序。

多个消费者监听同一个队列的问题似乎不是一个可行的解决方案,因为当消息批量到达时,它们将被循环传递给所有消费者,并且无法控制这将如何发生而且消息很容易乱序。

当我手动停止所有侦听器时,显然消息已按顺序处理。但是手动关闭和启动此类监听器绝对不是 HA 解决方案。

我们可以设置监控流程来检查系统的运行状况并根据需要关闭或启动它们,但这对我来说仍然太弱了。 事实上,我们想要的是让所有侦听器都启动并运行,但只有一个侦听器接收消息。如果那个人因为某种原因宕机了,那么另一个坐在那里的人将变得活跃并开始处理消息。

最初我们考虑使用主题而不是队列,但这会带来其他问题,如下所示:

    我们无法控制消息的来源 我们拥有的大量消息会给我们带来麻烦,因为我们的订阅者必须是持久的,因此在回来时必须处理大量待处理的消息 输入队列已经是集群的一部分,更改所有基础架构需要大量工作

无论如何,在我看来,它必须是一种现有的模式才能适应这种情况。任何帮助,建议将不胜感激。

解决方案不必是特定的 MQ 解决方案,欢迎提出任何想法。

提前致谢

【问题讨论】:

【参考方案1】:

在我看来,同步多个消费者并不是什么大问题,是最有效的解决方案。我不知道必须在哪里记录处理结果(也许 JMS 再次排队?),但我会在此之前尝试使用轻量级代理。您可以使用时间戳或通过 JMS 实现计数器来保持顺序。 消费者可以并行执行,然后在支持队列中发布。比单个代理可以使用队列浏览器和事务对它们进行排序。这个代理应该是“看门狗”的。

亚历山德罗

【讨论】:

谢谢 Alessandro 能否请您更具体地说明您对轻量级代理的含义。这是一个会附加计数器或分析时间戳的小消费者吗? 只是一个简短的说明,提到我尝试使用 JMSTimestamp 重新排序消息,但它不起作用。分析一个月工作的数据后发现,在某些情况下(相当多),我们会在同一毫秒内收到不止一条消息。最大值为每毫秒 22 条消息。【参考方案2】:

创建第二个队列,我们​​将其称为“控制队列”。在这个队列中,放入一条消息,我们称之为“令牌”。变更申请处理如下:

    在控制队列上侦听消息。 从同步点下的控制队列中获取令牌。 将相同的令牌消息放回控制队列,也在同步点下。 处理来自正常输入队列的事务,也在同步点下。 COMMIT 消息。 循环。

COMMIT 完成输入队列上的事务并使令牌对其他 MDB 可用。除了在同步点下具有令牌的 MDB 之外,不会对输入队列进行任何处理。但是,您可以让任意数量的 MDB 等待令牌。他们中的任何一个失败都会让其他人立即接管。

顺便说一句,不需要使用 XA。 WMQ 的单相 COMMIT 非常适用于此。

【讨论】:

非常感谢罗布。这看起来是一个很好的主意,也很有趣。我需要创建一个 POC 峰值,一旦我让它工作,我就会回来提供我的发现。 谢谢罗伯。一切都按预期工作。我注意到,与只有一个 MDB 消费者相比,处理整个测试批次的时间增加了一倍,与我的所有四个消费者并行运行(但消息乱序)相比,速度慢了大约八倍。无论如何它是有效的,我认为有一些方法可以改善处理时间。仍然很遗憾,在将消息写入队列时,无法将序列号附加到消息中。那会很好地解决我的问题。但是很好的建议,非常感谢。【参考方案3】:

当应用程序尝试通过其 MDB 侦听器使用队列时,我们可以通过使用 DEFSOPT(Exclusive) 定义队列来限制它们。这将确保只有一个应用程序可以使用该队列中的消息。

如果我们希望仅限于应用程序的一个实例,请将其定义为 NOSHARE。因此,一个应用程序的一个实例可以一次获取队列中的消息。当当前释放锁时,将轮到其他人。

【讨论】:

感谢您的建议。我希望我在同一个工作空间来验证它是如何工作的。不幸的是,在我的笔记本电脑上安装 WAS 实例和 MQ 管理器并测试您的解决方案对我来说并不容易。

以上是关于具有多个消费者但只有一个活动的 MQ 队列的主要内容,如果未能解决你的问题,请参考以下文章

MQ和redis对比

rabbitmq消息队列介绍

mq消息消费

消费端如何保证消息队列MQ的有序消费

MQ的订阅模式

mq中如何保证消费者顺序消费