JMS使用者阻止其他JMSXGroups

时间:2019-01-08 16:07:55

标签: java spring-boot apache-camel jms

我试图弄清楚是否有什么事情可以在消息回滚到队列时影响消费者的消息处理顺序。 我下面有一些简单的代码,可以帮助我重现此问题。 我只是将消息按特定顺序推入具有不同JMSXGroupIds的队列中:

  1. “ A1”(JMSXGroupId:1)
  2. “ B1”(JMSXGroupId:2)
  3. “ A2”(JMSXGroupId:1)
  4. “ C1”(JMSXGroupId:3)
  5. “ B2”(JMSXGroupId:2)

该代码使A1回滚(它最初重试该消息3次),并延迟返回到队列。但是,消费者然后等待,直到它可以再次提起A1(在等待了一段延迟的时间之后),这意味着B1和C1组被阻止在A1后面,并且从未得到处理。

理想情况下,我希望的是当A1放回队列并被告知等待时,消费者将拿起B1和C1 ...我最终想要做的是停止一个JMSXGroup阻止另一个在消费者身上。另外,可能值得补充的一点是,我需要保持A(A1,A2,A3 ...)的消息顺序,并且希望通过将它们放在队列中来做到这一点,而不是必须为异常构建一些管理解决方案。

onException(Exception.class)
            .log("Exception Caught !! ")
            .redeliveryDelay("1000")
            .maximumRedeliveries(3)
            .handled(false)
            .markRollbackOnly()
            .log("log:output");

    from("amq:queue:mailbox?concurrentConsumers=1")
            .to(logEndpoint)
            .process(exchange -> {
                if(exchange.getIn().getBody(String.class).contains("A")) {
                    throw new Exception("Found A");
                }
            });

我正在使用具有事务处理路由的基于Java的Apache Camel微服务。 没什么特别的,但是如果需要,我可以提供更多详细信息/配置详细信息。

预先感谢

3 个答案:

答案 0 :(得分:2)

在队列上严格排序必然会遇到这样的问题,因为队列必须遵守其基本的先进先出(即FIFO)语义。即使在A1失败后立即拾取B1,您也必须等待消耗A2直到消耗A1才能保持顺序,并且由于必须使用队列,所以FIFO将阻塞消耗C1和其他任何消息在它后面。

答案 1 :(得分:1)

您正在使用Camel的重新交付,它将仅重新交付调用处理器方法(例如,失败的地方),而不是整个路线。

您可能希望研究使用JMS事务,并让消息一直回滚到JMS代理,并在消息代理上配置重新交付设置。

如果您有《骆驼在行动》一书的副本,那么我建议您阅读事务一章和错误处理一章。

答案 2 :(得分:1)

您的问题是由于使用者端点上的concurrentConsumers=1。如果您只有一个使用者,则不能并行处理JMS组

有了这个限制,您实际上有一个Exclusive Consumer,并且 JMS组头不起作用,因为反正只有一个使用者可以处理消息。

JMSXGroupId标头可确保具有相同组ID的所有邮件均由同一使用者处理。因此,如果您有3个使用者,则即使消息A1在一段时间内“阻止”了A组的使用者,示例中的3个组也可以并行处理。

但是,当您的消费者数量少于组数量时,当然就是一种消息可以阻止其他组的原因,仅仅是因为一个消费者可以处理多个组。