The Java Management Extensions (JMX) technology is vastly used to build distributed Web-based, modular, and dynamic solutions for managing and monitoring devices, applications, and service-driven networks. In this blog, I will explain how one can enhance their application performance monitoring by using a JMX Connection Pool. By making use of connection pool you can boost over-all application performance.
Introduction
JMX is a JAVA technology framework for managing and monitoring applications, system objects, and devices that are hosted on the server. To monitor the state of the server, JMX uses the MBean(Managed Bean) servers. The MBean servers provide information with respect to the server’s resources such as memory details, garbage collection data, thread data, OS information, number of threads running on the server and available memory on the server. To read the state information of a server, a connection to the JMX server is required. Therefore, a pool of JMX connections can be shared among each client request.
JMX Connection pool is a cache of JMX connections, so that the JMX connections can be reused when future requests for the JMX connection arrive. For each client request, creating a new connection to the JMX server could be expensive in terms of system resource consumption. By reusing the JMX connections, we can improve the overall application performance.
These following sections discuss how a JMX Connection Pool is built using Apache-Commons Generic Pool API.
Solution
The solution uses the Apache Generic Object Pooling Framework which provides pooling functionality for any parameterized object. Here the parameterized object is the JMX connections.
The core components of the solution are listed as follows:
JmxPool
The com.xoriant.jmx.pool.JmxPool class provides the pooling functionality for JMX connections. The com.xoriant.jmx.pool.JmxPool uses the apache org.apache.commons.pool2.impl.GenericObjectPool class to implement the pool functionality.
The org.apache.commons.pool2.impl.GenericObjectPool class provides the following configurable parameters for the pool:
- How many connections a pool can have?
- How many idle objects can be allowed at a time in the pool?
- Testing a connection on borrow from the pool
- Testing a connection on return to the pool
- Testing a connection on create etc.
The following code snippet shows how the com.xoriant.jmx.pool.JmxPool class uses the GenericObjectPool:
public class JmxPool<Q> extends GenericObjectPool<Q> { public JmxPool(PooledObjectFactory<Q> factory) { super(factory); } public JmxPool(PooledObjectFactory<Q>factory,GenericObjectPoolConfig config) { super(factory, config); } }
The client of JmxPool pool passes the parameterized object for which the pool is created. For JMX connection, the client needs to pass javax.management.remote.JMXConnector as:
new JmxPool<JMXConnector>(new JmxPoolFactory<JMXConnector>(host, port));
JmxPoolFactory
The com.xoriant.jmx.pool.JmxPoolFactory provides the life-cycle methods for pooled object. The com.xoriant.jmx.pool.JmxPoolFactory extends class org.apache.commons.pool2.BasePooledObjectFactory and provides the following functionality for JMX connection:
- Creation
- Destruction
- Passivation
- Validation
These functionalities are implemented as follows:
Constructor
public JmxPoolFactory(Stringhost,Stringport) { this.host = host; this.port = port; }
This constructor initializes the data that is required to create a connection.
makeObject
@Override public PooledObject<Q> makeObject() throws Exception { return wrap(create()); }
The apache generic pool API calls the makeObject method to initiate the pool object creation process.
Wrap
@Override public PooledObject<Q>wrap(Q jmxConnector) { return new DefaultPooledObject<Q>(jmxConnector); }
The wrap method creates a new instance of the jmxConnector object so that the pool can track the state of the pooled object.
Create
@Override public Q create() throws Exception { // code to create connection JMXServiceURLurl = null; StringBuildervUrlString = newStringBuilder(”service:jmx:rmi:///jndi/rmi://”); vUrlString.append(host); vUrlString.append(port); url = new JMXServiceURL(vUrlString.toString()); return (Q)JMXConnectorFactory.connect(url, null); }
The create method creates the JMX connection to the server by using the server host and the port.
destroyObject
@Override public void destroyObject(PooledObject<Q>jmxPooledObject) throwsException { // close the connection here JMXConnectorjMXConnector =((JMXConnector)(jmxPooledObject.getObject())); jMXConnector.close(); }
The destroyObject method is called to close the JMX connection.
validateObject
@Override public boolean validateObject(PooledObject<Q>jmxPooledObject) { Boolean isValidConnection = Boolean.TRUE; try { (((JMXConnector)(jmxPooledObject.getObject()))).getMBeanServerConnection(); } catch (IOExceptione e) { isValidConnection = Boolean.FALSE; } return isValidConnection; }
The validateObject method is called before the pooled object is served to the client. If the connection is valid, it returns true. If the connection is not valid, it returns false.
Using the JmxPool and JmxPoolFactory classes
The com.xoriant.jmx.pool.JmxPoolManager class uses the core classes for pool implementation. The following section describes the functionality of JmxPoolManager.
JmxPoolManager
The com.xoriant.jmx.pool.JmxPoolManager class provides the facade implementation to the client. The manager class uses the factory and the pool class uses the client request for JMX connection.
The following code snippet shows how to use the com.xoriant.jmx.pool.JmxPool object:
public class JmxPoolManager { private JmxPool jmxPool; constructor public JmxPoolManager(String host, int port) { jmxPool= new JmxPool<JMXConnector>(new JmxPoolFactory<JMXConnector>(host,port)); } }
getConnectionFromPool
public JMXConnector getConnectionFromPool() { return pool.borrowObject(); }
This method requests a connection from the pool. If the connection is not available in the pool, it creates a new connection and provides it to the client. The method uses the borrowObject() method of the org.apache.commons.pool2.impl.GenericObjectPool.
returnConnectionToPool
public void returnConnectionToPool() { pool.returnObject(); }
This method returns the connection object back to the pool. The method uses the returnObject() method of the org.apache.commons.pool2.impl.GenericObjectPool.
cleanup
public void cleanup() { pool.close(); }
This method closes the pool. Once the pool is closed, borrowObject() fails with IllegalStateException.
Source download
Download the complete source code from the following link: https://github.com/xoriantcorporation/jmxpool.git
Reference
- http://docs.oracle.com/javase/tutorial/jmx/
- http://docs.oracle.com/javase/tutorial/jmx/mbeans/
- http://commons.apache.org/proper/commons-pool/