Why DefaultMessageListenerContainer should not use CachingConnectionFactory?
Asked Answered
B

1

14

I was reading spring documentation on DefaultMessageListenerContainer

It says "Note: Don't use Spring's CachingConnectionFactory in combination with dynamic scaling. Ideally, don't use it with a message listener container at all, since it is generally preferable to let the listener container itself handle appropriate caching within its lifecycle. Also, stopping and restarting a listener container will only work with an independent, locally cached Connection - not with an externally cached one."

Could anybody explain why?

Balzer answered 24/2, 2014 at 9:59 Comment(0)
C
19
  1. You really don't need to cache sessions for listener containers because the sessions are long lived; caching is very beneficial for frequent short use, such as with the JmsTemplate.
  2. The problem is really when cacheConsumers = true (the default). When using dynamic scaling and a listener is stopped, the session is returned to the cache but the broker doesn't know that nobody will actually consume from that session, so you are stuck with messages sitting in the cache that won't be read until that session happens to be reused when the volume increases.

Note: if you wish a JmsTemplate running on the container thread to participate in a container transaction, you should use a CachingConnectionFactory so the producers can be cached, but you should disable caching consumers in the factory if you have variable concurrency.

Counterfactual answered 24/2, 2014 at 13:57 Comment(11)
Thanks for the response and explanation Gary.Balzer
Gary just curious if a listener container or a DefaultMessageListenerContainer should not use a SingleConnectionFactory too. Since it is the superclass of the CachingConnectionFactory class.Embankment
Manual, no, that's ok; the problem is with caching consumers when using variable concurrency in the container; you can end up with a live consumer "stuck" in the cache.Counterfactual
Ok understood, I can use SingleConnectionFactory with a DefaultMessageListenerContainer. I have the problem when I have two DefaultMessageListenerContainer with setSubscriptionDurable true, therefore I need set two differents values for setClientId and setDurableSubscriptionName values. If I use SingleConnectionFactory or CachingConnectionFactory always I get "Could not refresh JMS Connection for destination 'topic://branch' - retrying in 5000 ms. Cause: setClientID call not supported on proxy for shared Connection. Set the 'clientId' property on the SingleConnectionFactory instead."Embankment
I around this problem using the ConnectionFactory directly for each DefaultMessageListenerContainer. If you know a better way, pls let me know.Embankment
Well, per the JMS spec, the clientId is a property of the connection so you can't share a single connection across different clientIds. The proxy does allow multiple containers to use the same clientId. See this code. You can still use SingleConnectionFactory but you need one for each unique clientId; they can wrap the same vendor connection factory (and the single connections can be shared for other uses - e.g. JmsTemplate).Counterfactual
Hi Gary .. could you please elaborate on point-2 in your answer above or probably provide a link/reference?Cheapen
I am not sure how much more elaboration you need. Let's say you have 5 consumers, and the workload drops so the container stops a consumer. If caching is in place, the consumer is left open and put in a cache instead of closing it. Since the broker doesn't know anything about this, he thinks it's still consuming so happily sends up to prefetch messages to it. Since the container is not using that consumer, nobody will see those messages until the workload in the other 4 containers increases such that it decides another consumer is needed and the cached consumer is again used.Counterfactual
@GaryRussell, regarding point 2, if dynamic scaling is not used, does that mean caching consumer will not be an issue? Does it provide more performance gain if consumer is cached (without dynamic scaling)? Regarding point 1- So sessions do not need to be cached, does that mean we can do CachingConnectionFactory.setSessionCacheSize(0) to turn it off? Does it matter if it is left to be default value, which is 1. Another question, If a fixed number of listeners used, for example 2, does that mean there will be 2 long lived sessions?Babcock
You should really ask a new question rather than commenting on an old one from more than 3 years ago. The admins here don't like extended commentary. As long as you don't have variable concurrency, it doesn't matter. Yes, there will be 2 long-lived sessions in that case.Counterfactual
@GaryRussell Thank you for the reply. I will do that next time.Babcock

© 2022 - 2024 — McMap. All rights reserved.