Chapter 15. Dead Connections and Session Multiplexing

In this section we will discuss connection time-to-live (TTL) and explain how JBoss Messaging deals with crashed clients and clients which have exited without cleanly closing their resources. We'll also discuss how JBoss Messaging multiplexes several sessions on a single connection.

15.1. Cleaning up Dead Connection Resources on the Server

Before a JBoss Messaging client application exits it is considered good practice that it should close its resources in a controlled manner, using a finally block.

Here's an example of a well behaved core client application closing its session and session factory in a finally block:

ClientSessionFactory sf = null;
ClientSession session = null;

try
{
   sf = new ClientSessionFactoryImpl(...);

   session = sf.createSession(...);
   
   ... do some stuff with the session...
}
finally
{
   if (session != null)
   {
      session.close();
   }
   
   if (sf != null)
   {
      sf.close();
   }
}
        

And here's an example of a well behaved JMS client application:

Connection jmsConnection = null;

try
{
   ConnectionFactory jmsConnectionFactory = new JBossConnectionFactory(...);

   jmsConnection = jmsConnectionFactory.createConnection();

   ... do some stuff with the connection...
}
finally
{
   if (connection != null)
   {
      connection.close();
   }
}
        

Unfortunately users don't always write well behaved applications, and sometimes clients just crash so they don't have a chance to clean up their resources!

If this occurs then it can leave server side resources, like sessions, hanging on the server. If these were not removed they would cause a resource leak on the server and over time this result in the server running out of memory or other resources.

We have to balance the requirement for cleaning up dead client resources with the fact that sometimes the network between the client and the server can fail and then come back, allowing the client to reconnect. JBoss Messaging supports client reconnection, so we don't want to clean up "dead" server side resources too soon or this will prevent any client from reconnecting, as it won't be able to find its old sessions on the server.

JBoss Messaging makes all of this configurable. For each ClientSessionFactory we define a connection TTL. Basically, the TTL determines how long the server will keep a connection alive in the absence of any data arriving from the client. If the client is idle it will automatically send "ping" packets periodically to prevent the server from closing it down. If the server doesn't receive any packets on a connection for the connection TTL time, then it will automatically close all the sessions on the server that relate to that connection.

If you're using JMS, the connection TTL is defined by the ConnectionTTL attribute on a JBossConnectionFactory instance, or if you're deploying JMS connection factory instances direct into JNDI on the server side, you can specify it in the xml config, using the parameter connection-ttl.

The default value for connection ttl is 300000ms, i.e. 5 minutes. A value of -1 for ConnectionTTL means the server will never time out the connection on the server side.

If you do not wish clients to be able to specify their own connection TTL, you can override all values used by a global value set on the server side. This can be done by specifying the connection-ttl-override attribute in the server side configuration. The default value for connection-ttl-override is -1 which means "do not override" (i.e. let clients use their own values).

15.2. Detecting failure from the client side.

In the previous section we discussed how the client sends pings to the server and how "dead" connection resources are cleaned up by the server. There's also another reason for pinging, and that's for the client to be able to detect that the server or network has failed.

As long as the client is receiving packets from the server it will consider the connection to be still alive. If the connection is idle the server will periodically send packets to the client to prevent the client from thinking the connection is dead.

If the client does not receive any packets for client-failure-check-period milliseconds then it will consider the connection failed and will either initiate failover, or call any FailureListener instances (or ExceptionListener instances if you are using JMS) depending on how it has been configured.

If you're using JMS it's defined by the ClientFailureCheckPeriod attribute on a JBossConnectionFactory instance, or if you're deploying JMS connection factory instances direct into JNDI on the server side, you can specify it in the jbm-jms.xml configuration file, using the parameter client-failure-check-period.

The default value for client failure check period is 5000ms, i.e. 5 seconds. A value of -1 means the client will never fail the connection on the client side if no data is received from the server. Typically this is much lower than connection TTL to allow clients to reconnect in case of transitory failure.

15.3. Session Multiplexing

Each ClientSessionFactory creates connections on demand to the same server as you create sessions. Each instance will create up to a maximum of maxConnections connections to the same server. Subsequent sessions will use one of the already created connections in a round-robin fashion.

To illustrate this, let's say maxConnections is set to 8. The first eight sessions that you create will have a new underlying connection created for them, the next eight you create will use one of the previously created connections.

The default value for maxConnections is 8, if you prefer you can set it to a lower value so each factory maintains only one underlying connection. We choose a default value of 8 because on the server side each packet read from a particular connection is read serially by the same thread, so, if all traffic from the clients sessions is multiplexed on the same connection it will all be processed by the same thread on the server, which might not be a good use of cores on the server. By choosing 8 then different sessions traffic from the same client can be processed by different cores. If you have many different clients then this may not be relevant anyway.

To change the value of maxConnections simply use the setter method on the ClientSessionFactory immediately after constructing it, or if you are using JMS use the setter on the JBossConnectionFactory or specify the max-connections parameter in the connection factory xml configuration in jbm-jms.xml.