druid配置项详解

时间:2025-05-07 16:03:55

源码地址

GitHub - alibaba/druid: 阿里云计算平台DataWorks(/document_detail/) 团队出品,为监控而生的数据库连接池

druid常用配置

# 创建DB连接4要素
=xxx
=xxx
=xxx
-class-name=

# 在数据库连接池首次创建的时候初始化几个连接
-size=5
# 最多可以激活的连接个数
-active=10
# 最小的数据库空闲连接个数
-idle=5
# 创建连接时的最大等待时长,一般这个不在意
-wait=60000
# 当执行数据库连接存活检查时,使用的通信sql语句
-query=SELECT 1 FROM DUAL
# 是不是在每次获取连接的时候都进行检查,设置为fale,对性能影响高
-on-borrow=false
# 是不是在每次归还(事务执行结束)连接的时候检查,对性能影响高
-on-return=false
# 是否在连接空闲的时候sql检查连接(这个参数只有在获取连接的时候才会使用)
-while-idle=true
# 在销毁线程中表示的是执行的时间间隔
# 在获取连接的时候,配合test-while-idle=true使用
# 表示的最小的空闲时间,大于这个时间才会进行sql检查连接
-between-eviction-runs-millis=60000
# 最小的连接空闲时间,小于这个时间不会进行回收
-evictable-idle-time-millis=3600000
# 是否开启会话保持,开启了之后如果在销毁的时候低于minidle的数量才会补充
-alive=true
# 开启了会话保持之后,对于不回收的连接
# 多长时间进行validateQuery一次校验,校验失败的话,还需要关闭异常链接并新建
-alive-between-time-millis=3600000

mysql进行jdbc连接

import .*;

public class JdbcDemo {
    public static void main(String[] args) {
        try {
            // 加载MySQL驱动程序
            ("");
            // 建立与MySQL的连接
            String url = "jdbc:mysql://localhost:3306/test";
            String user = "root";
            String password = "123456";
            Connection conn = (url, user, password);
            // 创建Statement对象
            Statement stmt = ();
            // 执行查询操作
            String sql = "SELECT * FROM users WHERE age > 18";
            ResultSet rs = (sql);
            // 处理查询结果
            while (()) {
                int id = ("id");
                String name = ("name");
                int age = ("age");
                (", name=" + name + ", age=" + age);
            }
            // 关闭资源
            if (rs != null) {
                ();
            }
            if (stmt != null) {
                ();
            }
            if (conn != null) {
                ();
            }
        } catch (ClassNotFoundException e) {
            ();
        } catch (SQLException
         e) {
            ();
        }
    }
}

druid各配置项生效原理

初始化过程

#init

 = new DruidConnectionHolder[];
 = new DruidConnectionHolder[];
 = new DruidConnectionHolder[];

while( < ) {
    try {
         pyConnectInfo = ();
        DruidConnectionHolder holder = new DruidConnectionHolder(this, pyConnectInfo);
        [++] = holder;
    } catch (SQLException var18) {
        ("init datasource error, url: " + (), var18);
        if () {
            connectError = var18;
            break;
        }

        (3000L);
    }
}

上面是连接池的初始化过程,数组长度是maxActive, 代表最多能拥有的连接个数,同时分为三个数组存放。

然后循环初始化数据库连接,保存至数据中,初始化的个数是initialSize个

线程任务

连接创建线程

通过信号量等控制线程运行,从而保持线程池数量。这个先不管

#run

连接销毁线程

#run

while(true) {
    try {
        if ( || ) {
            break;
        }

        if ( > 0L) {
            ();
        } else {
            (1000L);
        }

        if (()) {
            break;
        }

        ();
    } catch (InterruptedException var2) {
        break;
    }
}

timeBetweenEvictionRunsMillis:这个参数是标识这个线程需要sleep多久之后才能唤醒下一次销毁执行

#run

// 连接池的空闲数量 去除 最小保留的空闲连接
checkCount =  - ;

// 记录空闲时长
idleMillis = currentTimeMillis - ;
// 如果空闲时长 大于最小空闲时间 并且在保留的最小空闲连接之外则移除
if (idleMillis >= ) {
    if (checkTime && i < checkCount) {
        [evictCount++] = connection;
        continue;
    }

    // 如果空闲时间比最大的空闲时间还大,则直接移除
    if (idleMillis > ) {
        [evictCount++] = connection;
        continue;
    }
}

minEvictableIdleTimeMillis:空闲连接的最小保留时长,低于这个时间不会回收。高于这个时间,则移除比minIdle多出数量的连接。

maxEvictableIdleTimeMillis:默认7个小时,不管个数,空闲时间达到即移除。

通过keepalive参数进行保活
// 这个是不满足驱逐逻辑之后才执行的
// 如果设置了保持存活,且连接的空闲时间大于应该保持存活的时间了
if (keepAlive && idleMillis >= ) {
    [keepAliveCount++] = connection;
}

// 需要保活,且数量低于最小空闲连接,则需要补充,就是通过唤起创建线程补充
if (keepAlive &&  +  < ) {
    needFill = true;
}

keepAlive:是否需要保持连接存活

keepAliveBetweenTimeMillis:多久进行一次保活。

keepAliveConnections:有需要保活的连接,则利用validationQuery进行保活。保活失败,则重新创建连接,依赖于上述两个配置。

needFill:如果需要补充连接的话,也会重新创建连接。依赖于keepAlive以及连接数量情况。

获取连接过程

#getConnectionDirect

// testOnBorrow 参数的使用
if () {
    // 如果
    boolean validate = (, );
    if (validate) {
        break;
    }

    if (()) {
        ("skip not validate connection.");
    }

    ();
}

// testWhileIdle参数的使用
if (!) {
    break;
}

long timeBetweenEvictionRunsMillis = ;

// 只有空闲时间大于timeBetweenEvictionRunsMillis 这个时间,才会进行验证
if (idleMillis < timeBetweenEvictionRunsMillis && idleMillis >= 0L) {
    break;
}

// 验证失败就会丢弃连接
boolean validate = (, );
if (validate) {
    break;
}

();

testOnBorrow:获取连接的时候进行检测

testWhileIdle:获取连接的时候,且其空闲时间大于timeBetweenEvictionRunsMillis开始进行检测