What does a high Spring JMS DefaultMessageListenerContainer.receiveTimeout parameter mean?
Asked Answered
Q

1

8

I am getting into a project that implemented an IBM MQ listening Spring JMS application and I have troubles understanding the "receiveTimeout" in the DefaultMessageListenerContainer.

Compared to sources from the internet I think my project is kind of special that we are using a really high value of 30 seconds for the "receiveTimeout" parameter and I don't know what this actually means.

I have tried to figure out the meaning of the "receiveTimeout" parameter and I will give you my understanding below after the Spring configuration.

FYI: We are reading/processing many many messages from a queue that are all really small (about 100kb).

This is the spring configuration that we are using:

<bean id="msgListenerContainer"
        class="org.springframework.jms.listener.DefaultMessageListenerContainer"
        p:connectionFactory-ref="mqConnectionFactory" 
        p:messageListener-ref="myMessageListener" p:sessionTransacted="true"
        p:concurrentConsumers="1" p:maxConcurrentConsumers="20"
        p:receiveTimeout="30000" p:idleTaskExecutionLimit="10"
        p:idleConsumerLimit="5" />

If anyone is whondering about the different parameters here is what I have gathered throughout the internet:

The idleConsumerLimit property is used to specify the the maximum number of consumers that are allowed to be idle at a given time. Increasing this limit causes invokers to be created more aggressively. This can be useful to ramp up the number of consumers faster.

idleTaskExecutionLimit: The limit for the number of allowed idle executions of a receive task. The default is 1 causing idle resources to be closed early once a task does not receive a message. idleTaskExecutionLimit property is set to 10 to allow tasks to execute 10 times instead of the default value of 1.

receiveTimeout property is set to 30 seconds to tell the DMLC's receive operation to poll for message for 30 seconds instead of the default one second.

And here is my understanding:

So this means: If there is a heavy load Spring JMS will start up to 20 consumers (maxConcurrentConsumers) and as soon as the load goes down, these consumers will continue to read messages for 30 seconds (receiveTimeout) before closing or going idle. So after that 5 consumers (idleConsumerLimit) will still idle for 10 seconds (?) (idleTaskExecutionLimit) before closing down.

Please correct me if I am wrong.

One internet page stated that my consumers will only read a message every 30 seconds but I do not think that this is the right interpretation of "receiveTimeout".

One issue that we currently have is that we have many many GET's reading from the MQ but not actually getting a message - Like we can have 60'000 GET's that actually are able to read a message compared to 2'100'000 GET's that happend but did NOT read a message.

I am thankful for any help in understanding the behaviour of Spring JMS better.

Quillen answered 3/8, 2016 at 14:48 Comment(0)
A
3

The receive timeout is used when asking the broker client if there is more work (receive()) - it's not polling the broker, just polling the client library to see if the broker has sent any more messages. It has nothing to do with how often the messages are received.

When the timeout happens, the container immediately calls receive() again.

A high receive timeout means the container will be less responsive to stop() calls - the container can only stop between receive() calls.

Aggress answered 3/8, 2016 at 15:19 Comment(5)
And how often does the container actually call the 'receive()' method during those 30 seconds? And when does the container call the 'stop()' method? After the 30 seconds and after the following 'receive()' if there are no messages left in the queue?Quillen
The container thread calls the consumer receive() method continually (it blocks for the 30 seconds) while it is active. The container doesn't call stop() - you can call that, but it can only take effect "between" receives. Hence it stops faster with a shorter time.Aggress
Ah now I understand. If you actively call stop() it will still take those 30 seconds before actually doing it - referring to the receiveTimeout parameter. Thank you! Then again this is not important in my application because we never call the stop() method. I also get the feeling that I can not change the intervall the framework calls the receive() method. I am not sure if this issue I described is really an issue or just a normal behaviour of the framework as I lack the experience (having 2'100'000 gets while only getting 60'000 messages)Quillen
@GaryRussell I have to read 'n' number of messages per 'n' seconds. Example: I need to receive 10 message per every second. Can this be achieved by setting receiveTimeout to 1000 milliseconds and maxConcurrentConsumers to 10?Delgadillo
Don’t ask new questions in comments on 5 year old answers. Your use case is not clear. Ask a new question with much more detail.Aggress

© 2022 - 2024 — McMap. All rights reserved.