Tomcat / Spring连接池 - 列出连接项

时间:2016-05-19 17:45:34

标签: java spring tomcat

尝试调试与Missing connections in tomcat jdbc connection pool具有类似问题的应用程序。我目前正在使用:

  • Tomcat 6.0.32 - 公司要求
  • Tomcat JDBC Pool 1.0.9.3
  • Java 1.6.x - 公司要求
  • Spring 3.2.14
  • myBatis 3.2.8
  • Quartz 2.2.2

Spring Web请求以及使用Pool的Quartz触发作业混合在一起。大约5次运行后,我在池中没有更多可用连接,initialSize = 5,maxActive = 10。增加maxActive什么都不做,它只需要更长的时间,并且在池为空之前运行更多的Quartz。

2016-05-19 08:59:46,027 DEBUG org.springframework.scheduling.quartz.SchedulerFactoryBean#0_QuartzSchedulerThread   QuartzSchedulerThread.run  276 : batch acquisition of 1 triggers
2016-05-19 09:00:00,001 DEBUG org.springframework.scheduling.quartz.SchedulerFactoryBean#0_QuartzSchedulerThread   QuartzSchedulerThread.run  276 : batch acquisition of 0 triggers
2016-05-19 09:00:00,003 DEBUG org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-6   JobRunShell.run  201 : Calling execute on job DEFAULT.refMigrDetail
2016-05-19 09:00:00,003 DEBUG org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-6   DataSourceUtils.doGetConnection  110 : Fetching JDBC Connection from DataSource
2016-05-19 09:00:24,409 DEBUG org.springframework.scheduling.quartz.SchedulerFactoryBean#0_QuartzSchedulerThread   QuartzSchedulerThread.run  276 : batch acquisition of 0 triggers
2016-05-19 09:00:30,004 ERROR org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-6   CMRoreReferenceMigrator.run   93 : org.springframework.jdbc.CannotGetJdbcConnectionException: Could not get JDBC Connection; nested exception is java.sql.SQLException: [org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-6] Timeout: Pool empty. Unable to fetch a connection in 30 seconds, none available[10 in use].
2016-05-19 09:00:49,378 DEBUG org.springframework.scheduling.quartz.SchedulerFactoryBean#0_QuartzSchedulerThread   QuartzSchedulerThread.run  276 : batch acquisition of 0 triggers

到目前为止我做了什么:

  • 从Apache Commons DBCP切换到Tomcat JDBC Pool。这很有效。
  • 为Tomcat JDBC Pool启用了DEBUG。还在工作
  • 在Tomcat上启用JMX以使用jvisualvm监视连接池 - 这不起作用,因为Spring实际上是在创建池,而不是Tomcat。

在为Tomcat JDBC Pool启用DEBUG时,日志记录不会显示未释放连接的位置/原因。对于JMX路由,由于我没有使用Spring-Boot,我似乎无法在Spring中启用JMX来查看连接池。

我的问题是,有没有办法从SPRING(而不是Tomcat)中获取Spring Connection Pool对象/实例,然后通过它迭代所有连接,并列出每个连接上的一些简单属性,如活动,正在使用,关闭等...

我的想法是我只写了一些Java代码,它将连接池列表转储到Quartz作业之前和之后的日志中。转发我在Web应用程序之前和之后运行的关键Spring Web事务列表。

My Spring连接池配置,DB2数据库:

<bean id="rrfecfDataSource" class="org.apache.tomcat.jdbc.pool.DataSource" destroy-method="close">
    <property name="driverClassName" value="${rrfecf.datasource.jdbcDriver}" />
    <property name="url" value="${rrfecf.dataousrce.databaseUrl}" />
    <property name="username" value="${rrfecf.datasource.username}" />
    <property name="password" value="${password:rrfecf.datasource}" />
    <property name="initialSize" value="5" />
    <property name="maxActive" value="10" />
    <property name="defaultAutoCommit" value="false" />
    <property name="maxIdle" value="5" />
    <property name="minIdle" value="0" />
    <property name="testOnBorrow" value="true" />
    <property name="testOnReturn" value="false" />
    <property name="testWhileIdle" value="true" />
    <property name="validationQuery" value="SELECT CURRENT_DATE FROM sysibm.sysdummy1" />
    <property name="timeBetweenEvictionRunsMillis" value="600000" /> <!-- 10 minutes -->
    <property name="minEvictableIdleTimeMillis" value="900000" /> <!-- 15 minutes -->
</bean>

myBatis Spring配置:

<bean id="rrfecfSqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
    <property name="configLocation" value="WEB-INF/sqlMapConfig.xml"/>
    <property name="dataSource" ref="rrfecfDataSource" />
</bean>

1 个答案:

答案 0 :(得分:-1)

这似乎“有效”,不确定是否有更好的方法:

  • 在春天制作了一个ApplicationContextAware Bean。
  • 将ApplicationContextAware Bean连接到Quartz类。
  • 在Quartz类中我是:
    • 使用ApplicationContextAware Bean获取ConnectionPool。
    • 使用for循环迭代所有连接并转储属性

ApplicationContextAware类:

import org.apache.tomcat.jdbc.pool.DataSource;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

/**
 * <p>
 * The <code>BatchApplicationContextProvider</code> provides...
 * </p>
 */

public class BatchApplicationContextProvider implements ApplicationContextAware {

    public static final String ID              = BatchApplicationContextProvider.class.getName ();
    private String             SHORT_NAME      = "BatchApplicationContextProvider()";
    @SuppressWarnings("unused")
    private String              SYSTEM_IDENTITY = String.valueOf ( System.identityHashCode ( this ) );

    private ApplicationContext  context;

    /**
     * 
     */
    public BatchApplicationContextProvider() {
        // TODO Auto-generated constructor stub
    }

    /* (non-Javadoc)
     * @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext)
     */
    @Override
    public void setApplicationContext(ApplicationContext arg0)
        throws BeansException {
        this.context = arg0;
    }

    public ApplicationContext getApplicationContext() {
        return context;
    }

    public org.apache.tomcat.jdbc.pool.DataSource   getConnectionPool () { 
        return ( DataSource ) this.context.getBean ( "rrfecfDataSource" );
    }

}

样本用法:

public void        dumpConnectionPool () { 
    org.apache.tomcat.jdbc.pool.DataSource  lthePool = null;
    ConnectionPool  lbusyPool = null;
    try { 
        lthePool   = getBatchContext ().getConnectionPool ();
        lbusyPool  = lthePool.getPool ();
        if ( lbusyPool != null ) { 
            if ( lbusyPool.getSize () > 0 ) { 
                getLog().info ( SHORT_NAME + ".run() - ConnectionPool - size....................[" + lbusyPool.getSize () + "] idle [" + lbusyPool.getIdle () + "] active [" + lbusyPool.getActive () + "]"  );
                //getLog().info ( SHORT_NAME + ".run() - ConnectionPool - idle....................[" + lbusyPool.getIdle () + "]" );
                //getLog().info ( SHORT_NAME + ".run() - ConnectionPool - active..................[" + lbusyPool.getActive () + "]" );
                //PoolConfiguration       lpoolCfg = lbusyPool.getPoolProperties ();
            }
        }

        lbusyPool = null;
        lthePool = null;

    }
    catch ( Exception ltheXcp ) { 
        log.error ( ltheXcp );
    }
    finally { 

    }


}

我希望有人有一种更优雅的方式......这对我来说似乎是一种蛮力,但我现在需要在Web应用程序中解决这个问题。

编辑: dumpConnectionPool()存在问题... for循环似乎在迭代时挂起到所有连接,使它们全部“活动”。正在努力......

编辑: 取出for循环...设置connection = null似乎不会将其释放回连接池。

成功:

虽然不漂亮,但dumpConnectionPool()显示问题清单本身:

Quartz运行之前的dumpConnectionPool()显示5空闲,0活动:

2016-05-20 11:20:00,078  INFO org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-2   RunReferenceMigrator.run  138 : -----------------------------------------------------------------------------------------------------------------
2016-05-20 11:20:00,078  INFO org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-2   RunReferenceMigrator.dumpConnectionPool  257 : RunReferenceMigrator().run() - ConnectionPool - size....................[5] idle [5] active [0]
2016-05-20 11:20:00,078  INFO org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-2   RunReferenceMigrator.run  140 : -----------------------------------------------------------------------------------------------------------------

dumpConnectionPool()在Quartz运行之后,显示4个空闲,1个活动:

2016-05-20 11:24:45,063  INFO org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-2   RunReferenceMigrator.run  161 : -----------------------------------------------------------------------------------------------------------------
2016-05-20 11:24:45,063  INFO org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-2   RunReferenceMigrator.dumpConnectionPool  257 : RunReferenceMigrator().run() - ConnectionPool - size....................[5] idle [4] active [1]
2016-05-20 11:24:45,063  INFO org.springframework.scheduling.quartz.SchedulerFactoryBean#0_Worker-2   RunReferenceMigrator.run  163 : -----------------------------------------------------------------------------------------------------------------