Skip to main content

JMS connection pool problem / bug?

3 replies [Last post]
siggyuke
Offline
Joined: 2007-10-08

Hi All

is there a bug / problem with JMS connection pooling in Glassfish?

I've created a very simple remote client application based on the example code.
It works fine, in that it connects and send a message to the server. However, when the client connects it makes too many (I think) TCP socket connections.

at the call to

<br />
qcf = (QueueConnectionFactory)ctx.lookup(this.qcfName);<br />

3 tcp socket connections are made, to ports 3700, 37385 & 45039.

Then at the call to

<br />
qc = qcf.createQueueConnection();<br />

a further 8 tcp socket connections are made, to each port 37385 & 45039 - 8 being the number 'initial & minimum connections' in the connection pool settings.

- edited / added -
So, that's 19 tcp sockets open on the client to send jms messages to the server!
And if the pool gets to 32 connections then that'll be 67 tcp sockets open to the server!?!?

On the server we're seeing connections and active thread numbers increase by the same sort of figures as clients come on line.
- end of edited / added -

Given that my client will sit on 100+ PC's delivering status info to the server, all of these connections blow the threads in the thread pool of the server!?!?
(I thought that the connection pool would limit the number of connections to 32 - the default - farming ouy single connections to clients wanting to connect!).

So is JMS broken, or (more likely) miss configured / misunderstood by me?
Can anyone offer any advice?

Many thanks in advance

Pete

PS.
I'm starting this new smaller thread on the advice of 'eingfoan', as he thought my original one had way too much info to wade through. Thanks for the advice Eingfoan, and no I wasn't insulted. I'm always happy to receive constructive comments.

PPS.
here's my client code for anyone who want's view it:

<br />
package simplejmsclient;</p>
<p>import javax.jms.*;<br />
import java.util.Properties;<br />
import javax.naming.*;</p>
<p>public class SimpleJMSClient {<br />
    // details for making jms connection<br />
    private String serverIP = "serverIP";<br />
    private String serverPort = "3700";<br />
    private String qcfName = "jms/simpleCF";<br />
    private String qName = "jms/simpleQ";<br />
    // jms connection objects<br />
    QueueConnectionFactory qcf = null;<br />
    Queue q = null;<br />
    // a counter<br />
    static int counter = 0;<br />
    // sleep interval in seconds<br />
    long sleep = 10;</p>
<p>    // THIS IS A SIMPLE TEST PROGRAM, SO ERROR CHECKING IS MINIMAL<br />
    public static void main(String[] args)<br />
    {<br />
        SimpleJMSClient sjmsc = new SimpleJMSClient();</p>
<p>        sjmsc.doJMSinit();</p>
<p>        //send 10 messages<br />
        for(int i = 0; i < 10; i++)<br />
        {<br />
            // Assume that the app server is up and running<br />
            sjmsc.doJMSconn();</p>
<p>            // sleep between messages<br />
            try<br />
            {<br />
                Thread.sleep(sjmsc.sleep * 1000);<br />
            }<br />
            catch(Exception e)<br />
            {<br />
                e.printStackTrace();<br />
            }<br />
        }<br />
    }</p>
<p>    private void doJMSinit()<br />
    {<br />
        // the JNDI properties needed; ie. App server details<br />
        Properties props = new Properties();<br />
        props.setProperty("java.naming.factory.initial",<br />
                          "com.sun.enterprise.naming.SerialInitContextFactory");<br />
        props.setProperty("java.naming.factory.url.pkgs",<br />
                          "com.sun.enterprise.naming");<br />
        props.setProperty("java.naming.factory.state",<br />
                          "com.sun.corba.ee.impl.presentation.rmi.JNDIStateFactoryImpl");</p>
<p>        // optional.  Defaults to localhost.  Only needed if web server is running<br />
        // on a different host than the appserver<br />
        props.setProperty("org.omg.CORBA.ORBInitialHost", this.serverIP);<br />
        // need this or the above reverts to localhost for some reason<br />
        props.setProperty("org.omg.CORBA.ORBInitialPort", this.serverPort);</p>
<p>        //Create a JNDI API InitialContext object<br />
        Context ctx;<br />
        try<br />
        {<br />
            ctx = new InitialContext(props);</p>
<p>            qcf = (QueueConnectionFactory)ctx.lookup(this.qcfName);<br />
            q = (Queue)ctx.lookup(this.qName);<br />
        }<br />
        catch(NamingException ne)<br />
        {<br />
            ne.printStackTrace();<br />
            System.exit(1);<br />
        }<br />
    }</p>
<p>    private void doJMSconn()<br />
    {<br />
        try<br />
        {<br />
            QueueConnection qc = null;<br />
            QueueSession qs = null;<br />
            QueueSender qsdr = null;<br />
            TextMessage tm;</p>
<p>            try<br />
            {<br />
                qc = qcf.createQueueConnection();<br />
                qs = qc.createQueueSession(false, Session.AUTO_ACKNOWLEDGE);<br />
                String sm = "This is message " + this.counter++;<br />
                tm = qs.createTextMessage(sm);<br />
                System.out.println("Sending message: " + tm.getText());<br />
                qsdr = qs.createSender(q);<br />
                qsdr.send(tm);<br />
            }<br />
            finally<br />
            {<br />
                if(qc != null)<br />
                {<br />
                    qc.close();<br />
                }<br />
            }<br />
        }<br />
        catch(JMSException jmse)<br />
        {<br />
            jmse.printStackTrace();<br />
        }<br />
    }<br />
}<br />

Message was edited by: siggyuke

Message was edited by: siggyuke

Message was edited by: siggyuke

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
siggyuke
Offline
Joined: 2007-10-08

Okay, after reading my way through tonnes of doc's, the TCP sockets being opened on the client & the connections shown via the imqcmd command didn't tally with what the doc's said they should. All as explained in earlier posts.

After lots of experimentaion the solution seems to be setting the 'initial & max connection pool' to a value of 1. All else stays the same.
This set-up gives feedback (via imqcmd) that each client (message sender) gets 2 connections to the message handler / queue and each connection gets 2 threads allocated.

So, for example if init connection pool size is 1 & max pool size is 4, and 5 clients start sending messages, then imqcmd reports 10 new connections made and 20 new threads become active. I guess these 10 connections get farmed through the max 4 jms connections in the connection pool!?!??

Anyway, at least things are now starting to become a little more predictable.

However, all this seems to be against my understanding as to the point of connection pools!

I thought the whole point of having pools was so that ANY number of clients should be able to 'connect' TO THE POOL and thereby the server would never run out of resources!?!?
IE. if the pool was set up so that the init size was 8 and the max was 32, then when a client connects it gets a single connection to / from the pool. If 50 million clients try to connect, each only get one connection from a max pool size of 32. So the sever would only ever have a max of 32 connection and so 64 threads being active (given that each connection requires 2 threads per connection)!?!?

Any comments from anyone would be great.

Pete

Message was edited by: siggyuke

siggyuke
Offline
Joined: 2007-10-08

Does anyone use JMS on Glassfish?

perror
Offline
Joined: 2007-09-26

> Does anyone use JMS on Glassfish?

Yes, but they probably doesn't run in to your problems when they use it on the server side. I haven't read your code(!) but you probably doesn't get what you expect from your JNDI look up. You expect a plain ConnectionFactory (maybe a QueueConnectionFactory) but what you get is something wrapped in JMSJCA with a built in pool. On the server this i probably fine where multiple components running in the same jvm share the same pool but you get several pools on several jvms which i guess is pointless for you.

You could set up a separate connection factory for your clients with "Initial and Minimum Pool" = 1.

You could use a different object store and bypass JMSJCA and Glassfish completely or you could tie your code directly (new instead of JNDI look up) to Open MQ which Glassfish uses for JMS messaging.