Amey Jadiye opened SPR-13586 and commented
Spring provides classes for jms connection optimisation, however both SingleConnectionFactory and CachingConnectionFactory able to maintain only 1 TCP connection under the hood, Spring should have a PooledConnectionFactory which can pool multiple TCP connection and multiple session/consumer/producers under that, which can be better for throughPut and high load system.
No further details from SPR-13586
Comment From: spring-projects-issues
Juergen Hoeller commented
This is currently not on the roadmap for inclusion in Spring proper, since most JMS providers/drivers and all application servers ship a PooledConnectionFactory
variant of their own which is then able to use internal contracts for optimized pool processing, in particular when it comes to managing XA transactions.
The sweet spot for Spring's CachingConnectionFactory
is exactly that it reuses a single JMS Connection
and that it is based on generic JMS contracts, without any support for XA transactions but full support for native JMS transactions and all JMS acknowledge modes. This is a fine choice for many scenarios, and as far as we know, not provided anywhere else.
Juergen
Comment From: spring-projects-issues
Amey Jadiye commented
CachingConnectionFactory is best what its made for, i wish its functionality could be extended by caching multiple TCP connection, Yes agree many JMS providers provides PooledConnectionFactory but not all, adding pooling multiple conneciton will be a best combination for standalone application which only uses spring and not on JEE servers.
For performance many JMS application are not being deployed on EE servers and choose to have onyl org.springframework.jms.listener.DefaultMessageListenerContainer which is light waight and in this senario i also expect a PooledConnectionFactory which can give a better throughput.
Comment From: spring-projects-issues
Juergen Hoeller commented
Note that DefaultMessageListenerContainer
doesn't suggest a pooled ConnectionFactory
to begin with, since it internally has to hold on to one shared JMS Connection
per listener container and manages the Session
instances etc itself. A fully pooled ConnectionFactory
doesn't really add any value there, since we'd have to borrow a Connection
for the entire lifetime of each DefaultMessageListenerContainer
, with the pooling effectively being in vain.
All in all, CachingConnectionFactory
(or a fully pooled variant thereof) is primarily designed for JmsTemplate
usage or other code that temporarily borrows a JMS Connection
.
Juergen
Comment From: spring-projects-issues
Amey Jadiye commented
So in case if 1 jvm process is containing 10 DefaultMessageListenerContainer
, creating 10 CachingConnectionFactory
one per each doesnt looks like the optimal way, and all time they all are not working may be only 3 are working some times all of them are working, there has to be a shared and pooled connection in this case.
Holding one connection for life time is not so good, also the containers are having diffrent threads and they are running async and may require multiple connection at a time else they will chock on high load ,what do you think ?
In case we set CACHE_NONE = 0
PooledConnectionFactory will be much benifitial rather DefaultMessageListenerContainer
manage its own caching, and it will be optimal as well.
and yes for JmsTemplate
its better option.
Comment From: spring-projects-issues
Juergen Hoeller commented
In fact, I would not recommend a CachingConnectionFactory
for use with DefaultMessageListenerContainer
at all, and I would not recommend CACHE_NONE
either (unless you have to work with an externally provided XA connection pool). A DefaultMessageListenerContainer
is most efficient if it internally shares a JMS Connection
and caches the Session
/ @MessageConsumer
for each listener invoker. Since with native JMS, in order to be notified of an incoming message, there has to be an actively registered consumer against a session and therefore an underlying connection, it's a lot of internal re-registration effort otherwise - in particular if no new message came in to begin with.
From that perspective, I don't see the benefit of using a pooled connection factory over DefaultMessageListenerContainer
's default CACHE_CONSUMER
mode. If you're forced to use a pooled connection factory for XA purposes or for application server monitoring, then so be it, but I don't see why you would take that option without such a need.
Which JMS provider are you working with, BTW? Have you seen any concrete runtime indications where DefaultMessageListenerContainer
runs into a bottleneck that's caused by its locally managed JMS Connection
?
Juergen
Comment From: spring-projects-issues
Amey Jadiye commented
This need a long explaination, let me collection some data/code/benchmarking result and get back to you!
Comment From: spring-projects-issues
Amey Jadiye commented
I did few throughput tests on the CachingConnectionFactory
, to check you need 1 mysql server and 1 activemq server for this test https://github.com/ameyjadiye/mq-fury
there are 2 DefaultMessageListenerContainer
one is inserting random string in database and sending it to other listener, other listener is getting that message and checking whether its present in database, this test is just to check that always the transaction commit happening for mysql first then jms as well as how many messages are flowing between listeners.
Now here i tested the application with 2 configuration.
Wrapping vender’s ActiveMQConnectionFactory
in CachingConnectionFactory
Here I can see that only one TCP connection is getting established with netstat -ap | grep 61616 no matter how many container threads I’m using, with increasing concurrency
Using direct vendors ActiveMQConnectionFactory
This create big chaos as application is establishing lot many connection for each message sending and receiving, which I don’t want, but because of lot of simultaneous connections I can see lot of performance improvement in application
Though this test is made on ActiveMq and activemq may have some vendor specific connection factory, actually in production I’m using solace mq which is not giving any PooledConnectionFactory and all the connections should be managed at application side, again just to remind I am using DefaultMessageListenerContainer
directly and not in any Application server.
The solution is to have PooledConnectionfactory
which can have many parallel connection but in controlled manner.