How to register JCBC Tomcat 7 connection pool, create connection

I am trying to debug what appears to be an excessive number of database connections opening and closing despite the fact that we are using Tomcat 7 JDBC connection pooling. How can I register when getConnection () is called on the data source as a result of opening a new connection versus an existing connection that is borrowed from the pool?

+3


source to share


2 answers


I encountered a similar case today. I am logging slf4j and my problem was caused by hibernation.

What I did was set up in the log configuration the space where the JDBC connection receiver is called. Fortunately for hibernation there are debug level logs there.

<logger name="org.hibernate.engine.jdbc">
    <level value="debug"/>
</logger>

      

I guess for your case, you could try to do something equivalent with the namespace in which the JDBC pool receiver is called. It could be something like this:



<logger name="org.apache.tomcat.jdbc.pool">
    <level value="debug"/>
</logger>

      

Hope this helps. In hibernation, I get something like this:

DEBUG 02.07.2015 16:36:50,571 http-bio-8080-exec-33 (org.hibernate.engine.jdbc.internal.LogicalConnectionImpl.obtainConnection():212) [] - Obtaining JDBC connection
DEBUG 02.07.2015 16:36:50,601 http-bio-8080-exec-6 (org.hibernate.engine.jdbc.internal.LogicalConnectionImpl.obtainConnection():218) [] - Obtained JDBC connection
DEBUG 02.07.2015 16:36:50,627 http-bio-8080-exec-10 (org.hibernate.engine.jdbc.internal.LogicalConnectionImpl.obtainConnection():218) [] - Obtained JDBC connection
DEBUG 02.07.2015 16:36:50,643 http-bio-8080-exec-32 (org.hibernate.engine.jdbc.spi.SqlExceptionHelper.logExceptions():139) [] - Could not open connection [n/a]
org.apache.tomcat.dbcp.dbcp.SQLNestedException: Cannot get a connection, pool error Timeout waiting for idle object
    at org.apache.tomcat.dbcp.dbcp.PoolingDataSource.getConnection(PoolingDataSource.java:114)
    at org.apache.tomcat.dbcp.dbcp.BasicDataSource.getConnection(BasicDataSource.java:1044)

...

      

+1


source


I know of two ways to look at the Tomcat DB connection pool information.

1. Using JMX Monitoring

Tomcat connection pool will by default register as MBean (JMX Bean). This feature can be enabled / disabled using the jmxEnabled attribute in tomcat-jdbc-pool. See Tomcat JDBC Connection Pooling .

You can use various external JMX tools to monitor your DB connection pool and other JMX resources. I would suggest starting with JConsole that ships with Java. Launch JConsole, connect to JVM Tomcat (Catalina), select the MBeans header, open Catalina / DataSource / ... see Fig. Below.

JConsole shows the DataSource / DB connection pool

Learn more about Monitoring Tomcat .

2. Write a JdbcInterceptor class that registers DB connection pool information

Tomcat connection pooling allows you to register hooks for JDBC connections. Below, I'll show you how to write a JdbcInterceptor class that logs connection usage. Example for Tomcat 8, but it may work for Tomcat 7 too.

Add tomcat-jdbc.jar as provided dependency on your project.

    <dependency>
        <groupId>org.apache.tomcat</groupId>
        <artifactId>tomcat-jdbc</artifactId>
        <version>8.0.8</version>
        <scope>provided</scope>
    </dependency>

      



Create JdbcInterceptor class

This class uses the community entry, you can use something else.

package com.acme.rest.config;

import java.lang.reflect.Method;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.tomcat.jdbc.pool.ConnectionPool;
import org.apache.tomcat.jdbc.pool.JdbcInterceptor;
import org.apache.tomcat.jdbc.pool.PooledConnection;

public class MyConnectionPoolLogger extends JdbcInterceptor {

    private static final Log log = LogFactory.getLog(MyConnectionPoolLogger.class);

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        if (log.isDebugEnabled()) {
            String name = method.getName();
            if (CLOSE_VAL.equals(name)) {
                log.debug(String.format("Returning Connection to Pool [%s]", proxy));
            }
        }
        return super.invoke(proxy, method, args);
    }

    @Override
    public void reset(ConnectionPool connPool, PooledConnection conn) {
        if (connPool != null && conn != null) {
            if (log.isDebugEnabled()) {
                log.debug(String.format("Getting Connection [%s], Pool active=[%s], idle=[%s]", conn.toString(),
                        connPool.getActive(), connPool.getIdle()));
            }
        }
    }

    @Override
    public void disconnected(ConnectionPool connPool, PooledConnection conn, boolean finalizing) {
        if (connPool != null && conn != null) {
            if (log.isDebugEnabled()) {
                log.debug(String.format("Closing Connection [%s], Pool active=[%s], idle=[%s]", conn.toString(),
                        connPool.getActive(), connPool.getIdle()));
            }
        }
    }
}

      

Register this interceptor class in Context.xml

<Context>
  <Resource 
    name="jdbc/acmedb"
    auth="Container"
    type="javax.sql.DataSource"
    factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"

    jdbcInterceptors="org.apache.tomcat.jdbc.pool.interceptor.ConnectionState;
      org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer; 
      com.acme.rest.config.MyConnectionPoolLogger"

  />
</Context>

      

JdbcInterceptor classes can be registered as Resource , as shown above, or as POJO .

Sample magazines

Following are some examples of Tomcat logs when accessing connection pool

2017-11-04 00:15:19,389 DEBUG Getting Connection [PooledConnection[com.mysql.jdbc.JDBC4Connection@6dea96f]], Pool active=[1], idle=[0]
2017-11-04 00:15:19,393 DEBUG Returning Connection to Pool [ProxyConnection[PooledConnection[com.mysql.jdbc.JDBC4Connection@6dea96f]]]
2017-11-04 00:16:19,249 DEBUG Closing Connection [PooledConnection[com.mysql.jdbc.JDBC4Connection@6dea96f]], Pool active=[0], idle=[1]

      

0


source







All Articles