Spring JMS Concurrency and JMSXGroupID

2019-07-25 07:58发布

问题:

I'm using Spring JMS in my web application inside a TomEE container and I wanted to use JMSXGroupIDs to group my messages together. I use the following Spring JMS Listener Container configuration.

<jms:listener-container container-type="default" connection-factory="jmsFactory" cache="none" acknowledge="auto" transaction-manager="transactionManager" concurrency="1-5" >
    <jms:listener id="files-queue-listener" selector="mimetype ='application/xml'" destination="filesQueue" ref="filesQueueListener"/>
</jms:listener-container>

For a quick test, I sent 1000 messages grouped together by the same JMSXGroupID. I looked at the threads using VisualVM and I expected to see only one listener container active during the whole test. What happened is that the work is divided between the 5 message listener containers. I checked the ActiveMQ Web Console and as far as the broker is concerned, the messages were all sent to the same consumer. Is there any reason why the messages would be processed on different message listener container threads?

回答1:

First, some terminology - there is one container with 5 consumer threads (5 consumers from ActiveMQ's perspective).

I just ran a test with 5 fixed consumers and it worked as expected.

When I ran with variable consumers I did see messages with the same group id going to a "new" consumer when the container increased the consumer count; it then stabilized with the messages going to the same (new) consumer.

Since ActiveMQ is responsible for the distribution, it must be something in its algorithm when new consumers are created; I don't think it's anything to do with Spring.

Changing to a fixed number of consumers might be a viable workaround.

EDIT

Using variable consumers here is probably not a good idea anyway because when the container detects a slow down it will shutdown consumers - which will force ActiveMQ to start using a different consumer for any associated groups.



回答2:

Some more inputs (copied from tomee mailing list since it will not be automatically linked):

1- 1 jms session = 1 thread so if you don't use another Executor you will be processing messages in a single thread 2- spring uses an executor for the listener-container, this is the one to configure to tune the threading model