activemessaging with stomp和activemq.prefetchSize = 1

时间:2010-06-03 22:02:40

标签: ruby activemq stomp activemessaging

我有一种情况,我有一个有两个队列,Q1和Q2的activemq代理。我有两个使用activemessaging的基于ruby的消费者。我们称他们为C1和C2。两个消费者都订阅了每个队列。我在订阅每个队列时设置activemq.prefetchSize = 1。我也设置了ack = client。

考虑以下事件序列:

1)触发长时间运行作业的消息将发布到队列Q1。叫这个M1。

2)M1被分派给消费者C1,开始长时间的操作。

3)触发短作业的两条消息被发布到队列Q2。称这些为M2和M3。

4)M2被派遣到C2,快速完成短期工作。

5)即使C1仍在运行M1,M3也会被分派到C1。它能够调度到C1,因为prefetchSize = 1是在队列订阅上设置的,而不是在连接上。因此,已经调度Q1消息的事实不会阻止调度一条Q2消息。

由于activemessaging消费者是单线程的,因此最终结果是M3坐在C1上等待很长时间,直到C1完成处理M1。因此,M3不会被处理很长时间,尽管消费者C2处于闲置状态(因为它很快就完成了消息M2)。

基本上,无论何时运行长Q1作业,然后创建一大堆短Q2作业,恰好其中一个短Q2作业会停留在等待长Q1作业完成的消费者身上。

有没有办法在连接级别而不是在订阅级别设置prefetchSize?我真的不希望在处理M1时向C1发送任何消息。另一种选择是,我可以创建一个专门处理Q1的消费者,然后让其他消费者致力于处理Q2。但是,我宁愿不这样做,因为Q1消息很少 - Q1的专用消费者会在一天中大部分时间都处于空闲状态。

2 个答案:

答案 0 :(得分:2)

activemq.prefetchSize仅在SUBSCRIBE消息上可用,而不是CONNECT,根据其扩展的stomp标头(http://activemq.apache.org/stomp.html)的ActiveMQ文档。以下是相关信息:

  

动词:SUBSCRIBE

     

header:activemq.prefetchSize

     

type:int

     

description:指定最大值   将要发送的待处理消息数   被派遣到客户端。一旦这个   达到最大值不再有消息   被派遣到客户端   承认一条消息。设置为1表示   非常公平地分发消息   跨消费者在哪里加工   消息可能很慢。

我对此的阅读和体验是,由于M1尚未被确认(b / c您已启用客户端确认),因此该M1应该是订阅上设置的prefetchSize = 1所允许的1条消息。听到它不起作用我很惊讶,但也许我需要进行更详细的测试。您的设置应该符合您想要的行为。

我听说过其他人关于activemq dispatch的散乱,所以这可能是你正在使用的版本的错误。

我要提出的一个建议是,要么嗅探网络流量,看看M1是否因某种原因得到了确认,要么将一些put语句抛入ruby stomp gem以观察通信(这就是我通常结束的事情)在调试stomp问题时做的事情。)

如果我有机会尝试这一点,我会用自己的结果更新我的评论。

一个建议:很可能会发送多个长处理消息,如果长处理消息的数量超过了您的进程数,那么您将处于快速处理消息等待的此修复程序中。

我倾向于至少有一个专门的流程可以快速完成工作,或者换句话说,专门设置一组只能完成更长工作的流程。让所有轮询器消费者进程同时听取长短的结果可能会产生次优结果,无论发送的是什么。进程组是配置使用者收听目标子集的方法:http://code.google.com/p/activemessaging/wiki/Configuration

  

processor_group名称,   * list_of_processors

A processor group is a way to run the poller to only execute a subset of
     

处理器通过传递名称   poller命令行中的组   参数。

You specify the name of the processor as its underscored lowercase
     

版本。所以,如果你有一个   FooBarProcessor和BarFooProcessor in   一个处理器组,它看起来像   这样:

    ActiveMessaging::Gateway.define do |s|
      ...
      s.processor_group :my_group, :foo_bar_processor, :bar_foo_processor
    end

The processor group is passed into the poller like the following:

    ./script/poller start -- process-group=my_group

答案 1 :(得分:0)

我不确定ActiveMessaging是否支持此功能,但您可以在长处理消息到达时取消订阅其他消费者,然后在处理后重新订阅它们。

它应该会给你带来理想的效果。