简体   繁体   English

JMS使用者阻止其他JMSXGroups

[英]JMS Consumer blocking other JMSXGroups

I'm trying to figure out if there is anyway i can impact the Consumer's message processing order when a message is rolled back on to the queue. 我试图弄清楚在将消息回滚到队列时是否仍然可以影响消费者的消息处理顺序。 I have some simple code below that helps me reproduce the issue. 我下面有一些简单的代码,可以帮助我重现此问题。 I am simply pushing messages onto a queue with different JMSXGroupIds in a certain order: 我只是将消息按特定顺序推入具有不同JMSXGroupIds的队列中:

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

The code makes A1 rollback (it initially retries the message 3 times) and it goes back on to the queue with a delay. 该代码使A1回滚(它最初重试消息3次),并延迟返回到队列。 However, the consumer then waits until it can pick up A1 again (after waiting the delayed amount of time), meaning B1 and C1 groups are blocked behind A1 and never get processed. 但是,消费者随后等待,直到它可以再次取回A1(在等待了延迟的时间之后),这意味着B1和C1组被阻止在A1后面,并且从未得到处理。

Ideally what i was hoping for is that when A1 is put back on the queue and told to wait, the Consumer would pick up B1 and C1... what i'm ultimately trying to do is stop one JMSXGroup blocking the others on a Consumer. 理想情况下,我希望的是当A1放回队列并被告知等待时,消费者将接走B1和C1 ...我最终想要做的是停止一个JMSXGroup阻止另一个消费者。 Also, its probably worth adding that i need to keep message sequence order for A (A1,A2,A3...) and was hoping to do that by leaving them on the queue, rather than having to build some management solution for exceptions. 另外,可能值得补充的一点是,我需要保持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");
                }
            });

I am using a Java based Apache Camel micro-service with transacted routes. 我正在使用具有事务处理路由的基于Java的Apache Camel微服务。 Nothing really out of the ordinary but i can supply more detail/configuration details if needed. 没什么不寻常的,但如果需要,我可以提供更多详细信息/配置详细信息。

Thanks in advance 提前致谢

Strict ordering on a queue is bound to run into issues like this since the queue must adhere to its fundamental first-in-first-out (ie FIFO) semantics. 由于队列必须遵守其基本的先进先出(即FIFO)语义,因此严格排序队列肯定会遇到类似问题。 Even if B1 was picked up immediately after A1 failed you'd have to wait to consume A2 until A1 was consumed in order to preserve order, and since the queue must be consumed FIFO that would block the consumption of C1 and any of the other messages behind it. 即使在A1发生故障后立即拾取B1,您也必须等待消耗A2直到消耗A1才能保留顺序,并且由于必须使用队列,所以FIFO必须被使用,这会阻止C1和其他任何消息的消耗在它后面。

You are using Camel's redelivery which will only redelivery calling the processor method (eg where it failed) and not the entire route. 您正在使用Camel的重新交付,它将仅重新交付调用处理器方法(例如,失败的地方),而不是整个路线。

You may want to look at using JMS transactions and let the message rollback all the way to the JMS broker, and configure redelivery settings on the message broker. 您可能希望研究使用JMS事务,并让消息一直回滚到JMS代理,并在消息代理上配置重新交付设置。

If you have a copy of the Camel in Action book then I would suggest that you read the transaction chapter, and the error handling chapter. 如果您拥有《骆驼在行动》一书的副本,那么我建议您阅读事务一章和错误处理一章。

Your problem is because of the concurrentConsumers=1 on the consumer endpoint. 您的问题是由于使用者终结点上的concurrentConsumers=1 If you have just one consumer, it is impossible to process the JMS groups in parallel . 如果只有一个使用者,则不可能并行处理JMS组

With this limitation you effectively have an Exclusive Consumer and the JMS group header has no effect because there is only one consumer to process messages anyway. 有了这个限制,您就可以有效地拥有一个Exclusive Consumer ,并且JMS组头不起作用,因为无论如何,只有一个使用者可以处理消息。

The JMSXGroupId header makes sure that all messages with the same group ID are processed by the same consumer . JMSXGroupId标头可确保具有相同组ID的所有消息均由同一使用者处理 So if you would have 3 consumers, the 3 groups in your example could be processed in parallel even if message A1 "blocks" the consumer of group A for some time. 因此,如果您有3个使用者,则即使消息A1在一段时间内“阻止”了组A的使用者,示例中的3个组也可以并行处理。

However, when you have less consumers than groups , it is of course the case that one message can block other groups, simply because one consumer handles multiple groups. 但是,当使用者数量少于组数量时 ,当然会出现一条消息可以阻止其他组的情况,这仅仅是因为一个使用者可以处理多个组。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM