Camel-rabbitmq:在一个骆驼消费者中从多个rabbitmq队列消费

时间:2014-04-12 07:10:23

标签: rabbitmq apache-camel

我有以下情况:     生产者有3个rabbitmq队列,根据消息的优先级向其发送消息。(myqueue_high,myqueue_medium,myqueue_low)    我希望有一个单一的消费者,它可以按顺序或优先级从这些队列中提取,即只要消息存在,它就会一直从高位队列中拉出来。 o / w它从媒介中拉出来。如果介质也是空的,则从低位拉出。

我如何实现这一目标?我需要编写自定义组件吗?

1 个答案:

答案 0 :(得分:4)

将所有消息放入一个队列但具有不同优先级会更容易。这样,优先级排序将在代理中完成,Camel使用者将获得已按优先级排序的消息。但是,RabbitMQ实现了FIFO原则,并且还不支持优先级处理。

解决方案1 ​​

Camel允许您使用Resequencer基于某个比较器重新组织消息:https://camel.apache.org/resequencer.html

from("rabbitmq://hostname[:port]/myqueue_high")
    .setHeader("priority", constant(9))
    .to("direct:messageProcessing");

from("rabbitmq://hostname[:port]/myqueue_medium")
    .setHeader("priority", constant(5))
    .to("direct:messageProcessing");

from("rabbitmq://hostname[:port]/myqueue_low")
    .setHeader("priority", constant(1))
    .to("direct:messageProcessing");

// sort by priority by allowing duplicates (message can have same priority)
// and use reverse ordering so 9 is first output (most important), and 0 is last
// (of course we could have set the priority the other way around, but this way
// we keep align with the JMS specification...)
// use batch mode and fire every 3th second
from("direct:messageProcessing")
    .resequence(header("priority")).batch().timeout(3000).allowDuplicates().reverse()
    .to("mock:result");

这样,所有传入的消息都被路由到相同的子路由(direct:messageProcessing),其中消息根据传入路由设置的priority报头重新排序。

解决方案2

将SEDA与优先排序队列一起使用:

final PriorityBlockingQueueFactory<Exchange> priorityQueueFactory = new PriorityBlockingQueueFactory<Exchange>();
priorityQueueFactory.setComparator(new Comparator<Exchange>() {
    @Override
    public int compare(final Exchange exchange1, final Exchange exchange2) {
        final Integer prio1 = (Integer) exchange1.getIn().getHeader("priority");
        final Integer prio2 = (Integer) exchange2.getIn().getHeader("priority");
        return -prio1.compareTo(prio2);  // 9 has higher priority then 0
    }
});

final SimpleRegistry registry = new SimpleRegistry();
registry.put("priorityQueueFactory", priorityQueueFactory);

final ModelCamelContext context = new DefaultCamelContext(registry);
// configure and start your context here...

路线定义:

from("rabbitmq://hostname[:port]/myqueue_high")
    .setHeader("priority", constant(9))
    .to("seda:priority?queueFactory=#priorityQueueFactory");  // reference queue in registry

from("rabbitmq://hostname[:port]/myqueue_medium")
    .setHeader("priority", constant(5))
    .to("seda:priority?queueFactory=#priorityQueueFactory");

from("rabbitmq://hostname[:port]/myqueue_low")
    .setHeader("priority", constant(1))
    .to("seda:priority?queueFactory=#priorityQueueFactory");

from("seda:priority")
    .to("direct:messageProcessing");

解决方案3

如果在出现故障时需要持久性,请使用JMS,例如Camel的ActiveMQ组件而不是SEDA。只需将传入的消息从RabbitMQ转发到JMS目标,并设置JMSPriority标题。

解决方案4

完全跳过RabbitMQ,只需使用支持优先级的ActiveMQ等JMS代理。