Druid链接池一个设置引起的血案【abandon connection, open stackTrace】

今天在一台配置很低的机器上运行批量更新的程序~~~java

    大概跑了三十分钟~~~这配置~~~这程序~~~spring

    而后华丽丽的报异常了~~~sql

    具体异常是这样的,ui

DEBUG: (BaseJdbcLogger.java:132)    ooo Using Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@4d4e22e1]

[2014-07-17 15:19:35]5363945354 [Druid-ConnectionPool-Destory-1422598563] com.alibaba.druid.pool.DruidDataSource:1132 

WARN : (DruidDataSource.java:1132)   get/close not same thread

 

ERROR: (DruidDataSource.java:1815)   abandon connection, open stackTrace

        at java.lang.Thread.getStackTrace(Thread.java:1588)

    at com.alibaba.druid.pool.DruidDataSource.getConnectionDirect(DruidDataSource.java:942)

    at com.alibaba.druid.filter.FilterChainImpl.dataSource_connect(FilterChainImpl.java:4534)

    at com.alibaba.druid.filter.stat.StatFilter.dataSource_getConnection(StatFilter.java:661)

    at com.alibaba.druid.filter.FilterChainImpl.dataSource_connect(FilterChainImpl.java:4530)

    at com.alibaba.druid.pool.DruidDataSource.getConnection(DruidDataSource.java:880)

    at com.alibaba.druid.pool.DruidDataSource.getConnection(DruidDataSource.java:872)

    at com.alibaba.druid.pool.DruidDataSource.getConnection(DruidDataSource.java:97)

这个是最初的异常, 后面还有一大批异常,日志

Caused by: java.sql.SQLException: connection holder is null

    at com.alibaba.druid.pool.DruidPooledConnection.checkState(DruidPooledConnection.java:1085)

    at com.alibaba.druid.pool.DruidPooledConnection.getMetaData(DruidPooledConnection.java:825)

    at org.springframework.jdbc.support.JdbcUtils.extractDatabaseMetaData(JdbcUtils.java:285)

    ... 70 more

说什么holder为空code

    第一眼看到holder就像到Spring的源码, 里面处处是holder(笑)rem

    可是这里的holder不是Spirng里面的,是Druid的get

    这个holder大概是用来hou住链接池里面的链接的.源码

    而后为何为空了呢? 目测是哪一个连接坏了, 或者被意外的关闭了...it

    根据异常调源码  at com.alibaba.druid.pool.DruidDataSource.getConnectionDirect(DruidDataSource.java:942)

if (isRemoveAbandoned()) {

              StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();

              poolalbeConnection.setConnectStackTrace(stackTrace);

              poolalbeConnection.setConnectedTimeNano();

              poolalbeConnection.setTraceEnable(true);

 

              synchronized (activeConnections) {

                  activeConnections.put(poolalbeConnection, PRESENT);

              }

         }

 看不出啥来. 只能将日志继续看看, 仍是看不出啥来

    而后看了上面代码几遍后, 老以为 isRemoveAbandoned() 这个方法有鬼.

    查看调用处,:

 

恩, 这个DestroyConnectionThread很是可疑, 跳

if (isRemoveAbandoned()) {

   removeAbandoned();

}
public int removeAbandoned() {

        int removeCount = 0;

 

        long currrentNanos = System.nanoTime();

 

        List<DruidPooledConnection> abandonedList = new ArrayList<DruidPooledConnection>();

 

        synchronized (activeConnections) {

            Iterator<DruidPooledConnection> iter = activeConnections.keySet().iterator();

 

            for (; iter.hasNext();) {

                DruidPooledConnection pooledConnection = iter.next();

 

                if (pooledConnection.isRunning()) {

                    continue;

                }

 

                long timeMillis = (currrentNanos - pooledConnection.getConnectedTimeNano()) / (1000 * 1000);

 

                if (timeMillis >= removeAbandonedTimeoutMillis) {

                    iter.remove();

                    pooledConnection.setTraceEnable(false);

                    abandonedList.add(pooledConnection);

                }

            }

        } ....略

    }

擦, 这里不对头,   timeMillis >= removeAbandonedTimeoutMillis  timeMillis 这个是getConnection()被调用时的时间

    意思就是一个链接被get后, 超过了 removeAbandonedTimeoutMillis这么久我就弄死你.

    而后继续找removeAbandonedTimeoutMillis 这玩意在哪里设置的   ,最后发现是在

<property name="removeAbandoned" value="true" />

<property name="removeAbandonedTimeout" value="1800" />

    初始化配置的这里设置的,  这两个参数的大概意思就是, 

    经过datasource.getConnontion() 取得的链接必须在removeAbandonedTimeout这么多秒内调用close(),要不我就弄死你.(就是conn不能超过指定的租期)

    而后调成2个小时~~~

    而后程序成功跑完~~~华丽丽的等了50分钟

    总结:

    链接池为了防止程序从池里取得链接后忘记归还的状况, 而提供了一些参数来设置一个租期, 使用这个能够在必定程度上防止链接泄漏

    可是若是你的业务真要跑这么久~~~~那仍是注意下这个设置.

相关文章
相关标签/搜索