多个消费者的JMS队列

15

我有一个安装了HornetQ的JBoss-6服务器以及一个单一队列:

<queue name="my.queue">  
    <entry name="/queue/test"/>  
</queue>

有不同的消费者(在不同的机器上)连接到这个队列,但每次只有一个单一消费者处于活动状态。如果我关闭这个消费者,消息会立即被其他消费者中的一个处理。

由于我的消息需要耗费一定时间进行处理,因此我希望多个消费者同时处理它们独特的消息。

我记得在早期版本的JBoss中有类似的设置可以正常工作,但在Jboss-6中消息系统工作良好——除了上述问题。这个问题与Are multiple client consumers possible in hornetq?类似,但场景与我的不同。

更新1:如果我关闭(STRG+C)一个消费者,则会有一个短暂的超时(直到服务器识别到丢失的消费者),直到下一个消费者获取消息。

更新2:代码片段

VoidListener ml = new VoidListener();
QueueConnectionFactory qcf = (QueueConnectionFactory)
                             ctx.lookup("ConnectionFactory");
QueueConnection conn = qcf.createQueueConnection();
Queue queue = (Queue) ctx.lookup(queueName);
QueueSession session = conn.createQueueSession(false,
                                               QueueSession.AUTO_ACKNOWLEDGE);

QueueReceiver recv = session.createReceiver(queue,"");
recv.setMessageListener(ml);
conn.start();

还有消息监听器:

public class OlVoidListener implements MessageListener
{
  public void onMessage(Message msg)
  {
    counter++;
    logger.debug("Message ("+counter+") received");
    try {Thread.sleep(15*1000);} catch (InterruptedException e) {}
  }
}
2个回答

15

对于一个队列上有多个消费者的情况,消息会在这些消费者之间进行负载均衡。

如果您处理消息需要一定的时间,您应该通过设置consumer-window-size禁用缓冲。

HornetQ提供了一个示例分布式系统,演示如何禁用客户端缓冲并更好地支持慢速消费者(即处理消息需要一定时间的消费者)。

消息系统将预取/预读消息到客户端缓冲区以加快处理速度并避免网络延迟。如果您有快速处理队列及单个消费者,则这不是问题。

JBoss Messaging在连接工厂中提供了慢消费者选项,而Hornetq则提供了consumer window size。

大多数消息系统都会提供启用或禁用客户端预取的方法。


但是这是否解释了为什么“消费者A”正在处理消息,而“消费者B”处于空闲状态,并且队列中还有其他元素等待? - Thor
1
是的,消息系统将预取/预读消息到客户端缓冲区以加快处理速度并避免网络延迟。如果您拥有快速处理队列和单个消费者,则这不是问题。如果处理速度慢,则会出现问题。JBoss Messaging在连接工厂中提供了慢消费者选项,而Hornetq则提供了消费者窗口大小。大多数消息系统都会提供一种启用/禁用客户端预取的方法。我将其放在我的原始答案中。 - Clebert Suconic
这似乎是正确的答案,但不幸的是我无法激活<consumer-window-size>0</consumer-window-size>,请参见:https://dev59.com/QlrUa4cB1Zd3GeqPhCZF - Thor
1
我已经回答了你的另一个问题。你使用了错误的连接器。请查看你的hornetq-configuration.xml中正确的连接器。 - Clebert Suconic

2

非常抱歉,我无法理解问题的具体情况。我们在2.0.0.GA版本和2.2.2.Final版本中都使用了HornetQ,而且在这两种情况下,基于队列的负载均衡都能正常工作。如果您为一个队列定义了多个消费者,并且它们都处于活动状态,则消息将自动分发给它们。第一条消息发送给消费者A,第二条消息发送给消费者B,第三条消息发送给消费者C,以此类推。这就是多个消费者的队列工作方式——免费负载均衡 :) 当您关闭一个消费者时,其他消费者会接收更多的消息,这是正常的。


好的,你所描述的正是我预期的情况。但在我的设置中,即使有多个已连接的消费者(以及大量排队的消息),只有一个消费者会接收到消息。 - Thor
嗯...我和你的队列配置一样,没有其他配置更改。如果你遇到这样的问题,我会认为是你的消费者出了问题。你使用MDB吗? - omnomnom
消费者不是MDB,而是独立的Java程序。 - Thor
所以我强烈建议从消费者代码开始问题调查。你能贴一小段代码吗? - omnomnom

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接