简体   繁体   English

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

[英]How to log Tomcat 7 JDBC connection pool, connection creation

I'm trying to debug what seems to be an excessive number of database connections being opened and closed despite the fact that we are using the Tomcat 7 JDBC connection pool. 尽管事实上我们正在使用Tomcat 7 JDBC连接池,但我正在尝试调试看起来过多的数据库连接被打开和关闭。 How can I log when calling getConnection() on the data source results in a new connection being opened versus an existing connection being borrowed from the pool? 如何在数据源上调用getConnection()时导致打开新连接而不是从池中借用现有连接?

I have faced a similar case today. 我今天遇到过类似的情况。 I log through slf4j, and my problem was caused by hibernate. 我登录slf4j,我的问题是由hibernate引起的。

What I've done is setting up in the log configuration the space where the JDBC connection getter is called. 我所做的是在日志配置中设置调用JDBC连接getter的空间。 Fortunately, for hibernate there are logs at debug level there. 幸运的是,对于hibernate,存在调试级别的日志。

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

My guess is that for your case you can attempt to do something equivalent with the namespace where your JDBC pool getter is invoked. 我的猜测是,对于您的情况,您可以尝试执行与调用JDBC池getter的命名空间等效的操作。 It could be something like this: 它可能是这样的:

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

I hope this helps. 我希望这有帮助。 With hibernate I get something like this as a result: 有了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)

...

I know of two ways to look at the Tomcat DB Connection Pool info. 我知道有两种查看Tomcat数据库连接池信息的方法。

1. Using JMX Monitoring 1.使用JMX监控

The Tomcat Connection Pool by default will register itself as an MBean (JMX Bean). 默认情况下,Tomcat连接池将自己注册为MBean(JMX Bean)。 This feature can be turned on/off with the jmxEnabled attribute on the tomcat-jdbc-pool. 可以使用tomcat-jdbc-pool上的jmxEnabled属性打开/关闭此功能。 See The Tomcat JDBC Connection Pool . 请参见Tomcat JDBC连接池

You can use various external JMX tools to monitor the DB Connection Pool and other JMX resources. 您可以使用各种外部JMX工具来监视数据库连接池和其他JMX资源。 I would suggest starting with JConsole, which comes with Java. 我建议从带有Java的JConsole开始。 Launch JConsole, connect to your Tomcat (Catalina) JVM, select MBeans header, open Catalina/DataSource/... see pic below. 启动JConsole,连接到您的Tomcat(Catalina)JVM,选择MBeans标头,打开Catalina / DataSource / ...见下图。

JConsole显示DataSource / DB连接池

Read more on Monitoring Tomcat . 阅读有关监控Tomcat的更多信息。

2. Write a JdbcInterceptor class that logs DB Connection Pool info 2.编写一个记录数据库连接池信息的JdbcInterceptor类

The Tomcat connection pool allows you to register interceptors for JDBC Connections. Tomcat连接池允许您为JDBC Connections注册拦截器。 Below, I will show how to write a JdbcInterceptor class that logs connection usage. 下面,我将展示如何编写一个记录连接使用情况的JdbcInterceptor类。 The example is for Tomcat 8, but it might work for Tomcat 7 as well. 该示例适用于Tomcat 8,但它也适用于Tomcat 7。

Add tomcat-jdbc.jar as a provided dependency to your project. tomcat-jdbc.jar添加为项目提供的依赖项。

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

Create a JdbcInterceptor class 创建一个JdbcInterceptor类

This class uses commons logging, you may want to use something else. 这个类使用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()));
            }
        }
    }
}

Register this interceptor class in Context.xml 在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 either a Resource , as shown above, or as a POJO . JdbcInterceptor类可以注册为Resource ,如上所示,或者注册为POJO

Log Samples 记录样本

Below are some sample logs from Tomcat when accessing the Connection Pool 以下是访问连接池时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]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM