如何记录Tomcat 7 JDBC连接池,创建连接

时间:2014-09-18 16:22:00

标签: java tomcat jdbc tomcat7 connection-pooling

尽管我们正在使用Tomcat 7 JDBC连接池,但我正在尝试调试看起来过多的数据库连接被打开和关闭。如何在数据源上调用getConnection()时导致打开新连接而不是从池中借用现有连接?

2 个答案:

答案 0 :(得分:2)

我今天遇到过类似的情况。我登录slf4j,我的问题是由hibernate引起的。

我所做的是在日志配置中设置调用JDBC连接getter的空间。幸运的是,对于hibernate,那里有调试级别的日志。

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

我的猜测是,对于您的情况,您可以尝试执行与调用JDBC池getter的命名空间等效的操作。它可能是这样的:

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

我希望这会有所帮助。有了hibernate,我得到了这样的结果:

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 :(得分:1)

我知道有两种查看Tomcat数据库连接池信息的方法。

1.使用JMX监控

默认情况下,Tomcat连接池会将自身注册为MBean(JMX Bean)。可以使用tomcat-jdbc-pool上的jmxEnabled属性打开/关闭此功能。请参阅The Tomcat JDBC Connection Pool

您可以使用各种外部JMX工具来监视数据库连接池和其他JMX资源。我建议从带有Java的JConsole开始。启动JConsole,连接到您的Tomcat(Catalina)JVM,选择MBeans标头,打开Catalina / DataSource / ...见下图。

JConsole showing DataSource / DB Connection Pool

详细了解Monitoring Tomcat

2.编写一个记录数据库连接池信息的JdbcInterceptor类

Tomcat连接池允许您为JDBC Connections注册拦截器。下面,我将展示如何编写记录连接使用情况的JdbcInterceptor类。该示例适用于Tomcat 8,但它也适用于Tomcat 7.

tomcat-jdbc.jar 添加为项目提供的依赖项。

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

创建JdbcInterceptor类

此类使用公共日志记录,您可能希望使用其他内容。

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()));
            }
        }
    }
}

在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类可以注册为Resource,如上所示,也可以注册为POJO

记录样本

以下是访问连接池时来自Tomcat的一些示例日志

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]