Old thread, but I think this is a great idea. If you kick a PR or need assistance writing one, I’m happy to help and also take it for a spin in our test environment… we push a ton of messages through activemq and the amount of tcp connections is not optimal!
Sent from my iPhone > On Feb 16, 2023, at 5:47 AM, Jonathan Gallimore > <[email protected]> wrote: > > One of the things I've been looking into recently is the number of > connections that TomEE will make to an ActiveMQ broker. If you consider an > application that has 10 Message Driven Beans, and another bean that sends > messages using a connection factory, that application when started will > make 20 connections to ActiveMQ - 10 for the connection pool, and an > additional connection for each message driven bean. > > Conversely, I could create (and it occurs to me that I should) a Spring > application that listens on 10 destinations, sends messages from another > bean, and uses just 1 connection: a JMS connection is capable of managing > several sessions at the same time. At a small scale, the number of > connections isn't an issue, but if you have hundreds of applications > connecting to ActiveMQ, each making dozens of connections, this can become > a bit of a challenge. > > There are some options around this: > > * Have the MDBs use connections from the connection pool - this is already > possible using an activation property "ConnectionFactoryLookup", for > example: > > <Resource id="MyJmsResourceAdapter" type="ActiveMQResourceAdapter" > > class-name="org.apache.openejb.resource.activemq.ActiveMQResourceAdapter"> > # Do not start the embedded ActiveMQ broker > BrokerXmlConfig = > ServerUrl = tcp://localhost:61616 > UserName system > Password manager > </Resource> > > <Resource id="MyJmsConnectionFactory" > type="javax.jms.ConnectionFactory"> > ResourceAdapter = MyJmsResourceAdapter > PoolMaxSize 10 > PoolMinSize 0 > </Resource> > > <Container id="MyJmsMdbContainer" ctype="MESSAGE"> > ResourceAdapter = MyJmsResourceAdapter > activation.ConnectionFactoryLookup=MyJmsConnectionFactory > </Container> > > This means that the connections for the message driven beans will come from > the same pool as connections used to send messages, so you can at least > manage the full set. You'll still need at least <number of mdbs> + 1 > connections in that pool, however. > > * Override the resource adapter behaviour where connections are created. > Connections are made here: > https://github.com/apache/tomee/blob/main/container/openejb-core/src/main/java/org/apache/openejb/resource/activemq/jms2/TomEEManagedConnectionFactory.java#L67. > I hacked up some code to override makeConnection(): > > private final Map<ActiveMQConnectionRequestInfo, ActiveMQConnection> > physicalConnections = new HashMap<>(); > > @Override > public ActiveMQConnection makeConnection(ActiveMQConnectionRequestInfo > connectionRequestInfo, ActiveMQConnectionFactory connectionFactory) throws > JMSException { > ActiveMQConnection activeMQConnection = null; > > if (singleton) { > synchronized (this) { > activeMQConnection = > physicalConnections.get(connectionRequestInfo); > if (activeMQConnection == null) { > activeMQConnection = > super.makeConnection(connectionRequestInfo, connectionFactory); > physicalConnections.put(connectionRequestInfo, > activeMQConnection); > } > } > } else { > activeMQConnection = > super.makeConnection(connectionRequestInfo, connectionFactory); > } > > return activeMQConnection; > } > > The idea here is that only one physical connection per > username/password/client ID combination would be created, and can be shared > by different sessions. I added a parameter to the connection factory called > "singleton" (perhaps needs a better name) to turn this behaviour on. > > The good news is that broadly speaking, it does work - I'm working on some > itests, but unit tests and actually running TomEE and ActiveMQ look good. > > Does anyone have any thoughts or reservations on this (or any specific > cases that ought to be tested)? > > Jon
