ASG
IBM
Zystems
Cressida
Icon
Netflexity
 
  MQSeries.net
Search  Search       Tech Exchange      Education      Certifications      Library      Info Center      SupportPacs      LinkedIn  Search  Search                                                                   FAQ  FAQ   Usergroups  Usergroups
 
Register  ::  Log in Log in to check your private messages
 
RSS Feed - WebSphere MQ Support RSS Feed - Message Broker Support

MQSeries.net Forum Index » IBM MQ Java / JMS » Failed connection attempts leak memory?

Post new topic  Reply to topic
 Failed connection attempts leak memory? « View previous topic :: View next topic » 
Author Message
terlisimo
PostPosted: Wed Dec 23, 2009 11:49 pm    Post subject: Failed connection attempts leak memory? Reply with quote

Newbie

Joined: 09 Nov 2009
Posts: 8

Hello,

If the queue manager is unavailable due to service being offline or network connectivity problems, the application should be attempting to reconnect forever.

I found that MQ classes leak about 4kb of memory per connection attempt. Some internal MQ class keeps a RemoteTCPConnection object referenced, see snapshot data (8640 connect attempts):

http://imgur.com/3W6dA

The application works like this (simplified):

Code:

while (!bConnected) {
    try {
        conn = connectionFactory.createConnection();
        bConnected = true;
    }
    catch(Exception e) {
        LOG.error("Unable to connect, sleeping 10 seconds.");
    }
    Thread.sleep(10000);
}


So, attempting to reconnect every 10 seconds leaks about 32MB of memory per day which is not really nice for a server application.
Increasing the reconnect interval to 5 minutes makes this 32MB per month which is not that bad but is only delaying memory problems.

I made a workaround by attempting to create a TCP socket connection to the MQ server host/port before attempting to connect to a server via MQ classes.
It seems to work fine.

Am I doing something wrong here? Is there a better way to handle Websphere MQ connection attempts?

I'm running WMQ 7.0.1, using JMS and MQTopicConnectionFactory.
Back to top
View user's profile Send private message
rekarm01
PostPosted: Thu Dec 24, 2009 3:01 am    Post subject: Re: Failed connection attempts leak memory? Reply with quote

Grand Master

Joined: 25 Jun 2008
Posts: 1415

How about trying to close the connection?
Code:
while (!bConnected) {
    try {
        conn = connectionFactory.createConnection();
        bConnected = true;
    }
    catch(JMSException e) {
        if (conn != null)
            try { conn.close(); }
            catch(JMSException e) {}
        LOG.error("Unable to connect, sleeping 10 seconds.");
        Thread.sleep(10000);
    }
}
Back to top
View user's profile Send private message
terlisimo
PostPosted: Thu Dec 24, 2009 3:56 am    Post subject: Reply with quote

Newbie

Joined: 09 Nov 2009
Posts: 8

Tried that but in practice if connectionFactory.createConnection() throws an Exception then the connection object is never really created so it remains remains null and there's nothing to close.
Back to top
View user's profile Send private message
terlisimo
PostPosted: Thu Dec 24, 2009 5:41 am    Post subject: Reply with quote

Newbie

Joined: 09 Nov 2009
Posts: 8

I am stupid.

My app leaked memory because every time it tried to connect it would create a new ConnectionFactory object. Simplified code is too simplified

The old ConnectionFactory would be gracefully GC'd but it would add the "failed" connection object to the internal TCP Connection Pool so those "failed" connection objects were never released/GC'd nor reused.

The solution was to create a singleton connectionFactory factory which ensured that there can be only one CF object instantiated and the leak went away.

EDIT:
The solution still leaks


Last edited by terlisimo on Sun Dec 27, 2009 6:10 am; edited 1 time in total
Back to top
View user's profile Send private message
Vitor
PostPosted: Thu Dec 24, 2009 5:51 am    Post subject: Reply with quote

Grand High Poobah

Joined: 11 Nov 2005
Posts: 26093
Location: Texas, USA

terlisimo wrote:
I am stupid.


It happens to us all.

I found it stopped bothering me after the first 100 or so times...

As a slight aside to your originial post, I would question the wisdom of an application that attempts to reconnect "forever". Absolutely it should try and reconnect, and absolutely it should make a number of attempts over a significant period of time (both time and number calculated according to local considerations).

But at some point it should give up, so as to highlight the fact there's a problem. Granted that whatever you've got monitoring queue manager and network should spot the problem, but nothing says "page the on-call person" like a downed application.

Unless of course the application, while attempting reconnection, has some means of pinging the monitoring software directly.

My 2 cents, other views probably valid, Merry Xmas to all.
_________________
Honesty is the best policy.
Insanity is the best defence.
Back to top
View user's profile Send private message
terlisimo
PostPosted: Sun Dec 27, 2009 6:08 am    Post subject: Reply with quote

Newbie

Joined: 09 Nov 2009
Posts: 8

There is a leak after all, even when using only one connection factory.

If ConnectionFactory.createConnection method is called and the remote system refuses TCP connection, the application keeps referencing com.ibm.mq.jmqi.remote.internal.RemoteTCPConnection for each failed connection attempt.

Here's a simple app that demonstrates this behavior. Just point it to a host/port that is not listening. Requires WMQ client 7.0+.

Code:

import javax.jms.JMSException;
import com.ibm.mq.jms.MQTopicConnectionFactory;
import com.ibm.msg.client.wmq.WMQConstants;

public class MQLeak {

    public static void main(final String[] p_args) throws JMSException {

        MQTopicConnectionFactory cf = null;
        cf = new MQTopicConnectionFactory();

        int i = 0;
        while (i < 2000) {
            cf.setPort(1414);
            cf.setHostName("localhost");
            cf.setIntProperty(WMQConstants.WMQ_CONNECTION_MODE, WMQConstants.WMQ_CM_CLIENT);
            cf.setQueueManager("TEST");
            cf.setChannel("TEST");
            cf.setUseConnectionPooling(true);

            try {
                cf.createConnection();
            }
            catch (JMSException e) {
                if (i % 100 == 0) {
                    System.out.println(i);
                }
            }

            i++;
        }
    }
}


The workaround:

before calling connect, try opening a socket connection to the destination broker, like so:

Code:
private static boolean pingHostPort(String p_host, int p_port) {
    Socket socket;
    try {
        socket = new Socket(p_host, p_port);
        socket.close();
        socket = null;
    }
    catch (Exception e) {
        return false;
    }
    return true;
}


I guess I'll open a PMR and see what the big boys say.
Back to top
View user's profile Send private message
fjb_saper
PostPosted: Sun Dec 27, 2009 2:56 pm    Post subject: Reply with quote

Grand High Poobah

Joined: 18 Nov 2003
Posts: 20756
Location: LI,NY

Don't know about your test, but I wonder if keeping the CF initialization in the loop would have something to do with it...

Try the same with moving the CF initialization outside of the loop.

Have fun
_________________
MQ & Broker admin
Back to top
View user's profile Send private message Send e-mail
terlisimo
PostPosted: Sun Jan 31, 2010 11:22 pm    Post subject: Reply with quote

Newbie

Joined: 09 Nov 2009
Posts: 8

I can confirm that this was a real memory leak and that it is fixed in Websphere Client 7.0.1.1

Back to top
View user's profile Send private message
Michael Dag
PostPosted: Mon Feb 01, 2010 12:46 am    Post subject: Reply with quote

Jedi Knight

Joined: 13 Jun 2002
Posts: 2607
Location: The Netherlands (Amsterdam)

Do you have a PTF or APAR number?
_________________
Michael



MQSystems Facebook page
Back to top
View user's profile Send private message Visit poster's website MSN Messenger
terlisimo
PostPosted: Mon Feb 01, 2010 1:01 am    Post subject: Reply with quote

Newbie

Joined: 09 Nov 2009
Posts: 8

I think it was one of these:

http://www-01.ibm.com/support/docview.wss?rs=171&uid=swg1IZ56280

http://www-01.ibm.com/support/docview.wss?rs=171&uid=swg1IC61714

http://www-01.ibm.com/support/docview.wss?rs=171&uid=swg1IZ60328
Back to top
View user's profile Send private message
Michael Dag
PostPosted: Mon Feb 01, 2010 1:06 am    Post subject: Reply with quote

Jedi Knight

Joined: 13 Jun 2002
Posts: 2607
Location: The Netherlands (Amsterdam)

Thanks!
_________________
Michael



MQSystems Facebook page
Back to top
View user's profile Send private message Visit poster's website MSN Messenger
Display posts from previous:   
Post new topic  Reply to topic Page 1 of 1

MQSeries.net Forum Index » IBM MQ Java / JMS » Failed connection attempts leak memory?
Jump to:  



You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
Protected by Anti-Spam ACP
 
 


Theme by Dustin Baccetti
Powered by phpBB © 2001, 2002 phpBB Group

Copyright © MQSeries.net. All rights reserved.