美文网首页
Druid配置参数详解-removeAbandoned,logA

Druid配置参数详解-removeAbandoned,logA

作者: codeimport | 来源:发表于2020-01-02 22:26 被阅读0次

    Druid配置参数详解-removeAbandoned,logAbandoned,removeAbandonedTimeoutMillis

    Druid是一个由阿里开源的数据库连接池,Druid的配置非常丰富,但是设置不当会对生产环境造成严重影响,网上Druid的资料虽多,但大部分都是互相复制粘贴,有很多不准确甚至完全错误的描述,Druid已经开源很久,而且作者WenShao的工作重心也已经不在Druid上,有些功能估计他自己都不太了解了。本系列将从源代码的角度分析Druid目前的最新版本(1.1.21)各个常用的配置项的具体含义以及是怎么起作用的。

    画外音:目前Druid在开源中国举办的2019年度最受欢迎中国开源软件中排名第7名,支持Druid的朋友可以去投票哇。2019年度最受欢迎中国开源软件

    removeAbandoned,logAbandoned,removeAbandonedTimeoutMillis是什么意思?

    removeAbandoned:如果连接泄露,是否需要回收泄露的连接,默认false;
    logAbandoned:如果回收了泄露的连接,是否要打印一条log,默认false;
    removeAbandonedTimeoutMillis:连接回收的超时时间,默认5分钟;

    画外音:这两个参数笔者认为非常重要,但是不知为何,Druid默认是不开启的,并且官方的配置例子中也没有配置这两个参数:Druid官方配置笔者就因为没有配置这两个参数,曾经吃过大亏

    removeAbandoned,logAbandoned,removeAbandonedTimeoutMillis有什么用?

    举个栗子:笔者当初做过单个事务使用多数据源的功能,重写了Spring的ConnectionHolder,由于笔者的疏忽,每次从ConnectionHolder中获取连接时都获取到了两条连接,但是只是使用了其中的一条,相当于另一条连接只是从连接池中拿出来了,但是再也不会还回去了,这样就导致了连接池中的连接很快就消耗光了,即activeCount=maxActive。

    如果当时我设置了removeAbandoned就不会出现这个问题,应该Druid会定期检查池中借出去的连接是否处于运行状态,如果不是处于运行状态,并且借出时间超过removeAbandonedTimeoutMillis(默认5分钟)就会回收该连接。

    连接是怎么回收的?

    Druid每隔timeBetweenEvictionRunsMillis(默认1分钟)会调用DestroyTask,在这里会判断是否可以回收泄露的连接

        public class DestroyTask implements Runnable {
            public DestroyTask() {
    
            }
    
            @Override
            public void run() {
                shrink(true, keepAlive);
                //判断removeAbandoned是否为true,默认是false,不知为何
                if (isRemoveAbandoned()) {
                    removeAbandoned();
                }
            }
    
        }
    
    
                for (; iter.hasNext();) {
                    DruidPooledConnection pooledConnection = iter.next();
                    
                    //判断该连接是否还在运行,只回收不运行的连接
                    //Druid会在连接执行query,update的时候设置为正在运行,
                    // 并在回收后设置为不运行
                    if (pooledConnection.isRunning()) {
                        continue;
                    }
    
                    long timeMillis = (currrentNanos - pooledConnection.getConnectedTimeNano()) / (1000 * 1000);
                    
                    //判断连接借出去的时间大小
                    if (timeMillis >= removeAbandonedTimeoutMillis) {
                        iter.remove();
                        pooledConnection.setTraceEnable(false);
                        abandonedList.add(pooledConnection);
                    }
                }
    
                    //判断是否要记录连接回收日志,这个很重要,可以及时发现项目中是否有连接泄露
                    if (isLogAbandoned()) {
                        StringBuilder buf = new StringBuilder();
                        buf.append("abandon connection, owner thread: ");
                        buf.append(pooledConnection.getOwnerThread().getName());
                        buf.append(", connected at : ");
                        buf.append(pooledConnection.getConnectedTimeMillis());
                        buf.append(", open stackTrace\n");
                    }
    

    总结

    笔者认为这三个参数非常重要,但是官方默认是不开启的,建议使用Druid的项目都设置这三个参数,这样可以有效的发现代码中是否有连接泄露。

    相关文章

      网友评论

          本文标题:Druid配置参数详解-removeAbandoned,logA

          本文链接:https://www.haomeiwen.com/subject/wtdioctx.html