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

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

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

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

   

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

    

我希望这有帮助。 有了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) ... 

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

1.使用JMX监控

默认情况下,Tomcat连接池将自己注册为MBean(JMX Bean)。 可以使用tomcat-jdbc-pool上的jmxEnabled属性打开/关闭此function。 请参见Tomcat JDBC连接池 。

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

JConsole显示DataSource / DB连接池

阅读有关监控Tomcat的更多信息。

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

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

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

   org.apache.tomcat tomcat-jdbc 8.0.8 provided  

创建一个JdbcInterceptor类

这个类使用commons日志记录,你可能想要使用其他东西。

 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中注册此拦截器类

    

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]