zoukankan      html  css  js  c++  java
  • 摘要: Druid连接池一个设置引发的血案 -- 链接池出现问题

    摘要: Druid连接池一个设置引发的血案

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

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

        然后华丽丽的报异常了~~~

        具体异常是这样的,

    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为空

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

        但是这里的holder不是Spirng里面的,是Druid的

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

        然后为什么为空了呢? 目测是哪个链接坏了, 或者被意外的关闭了...

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

    941         if (isRemoveAbandoned()) {
    942                StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
    943                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分钟

        总结:

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

        但是如果你的业务真要跑这么久~~~~那还是注意下这个设置.

  • 相关阅读:
    CS224n, lec 10, NMT & Seq2Seq Attn
    CS231n笔记 Lecture 11, Detection and Segmentation
    CS231n笔记 Lecture 10, Recurrent Neural Networks
    CS231n笔记 Lecture 9, CNN Architectures
    CS231n笔记 Lecture 8, Deep Learning Software
    CS231n笔记 Lecture 7, Training Neural Networks, Part 2
    pytorch坑点排雷
    Sorry, Ubuntu 17.10 has experienced an internal error
    VSCode配置python插件
    tmux配置与使用
  • 原文地址:https://www.cnblogs.com/water-1/p/6843960.html
Copyright © 2011-2022 走看看