1、简介
在本文中,我们将测试 Druid 连接池配置参数 testWhileIdle 的作用。
2、环境
os-window10druid-1.2.8jdk-1.8.0_312maven-3.8.1
复制代码
3、配置 testWhileIdle 运行效果
3.1、启动测试类
DruidDataSource dataSource = new DruidDataSource();dataSource.setUrl("jdbc:mysql://ip:port");dataSource.setUsername("name");dataSource.setPassword("password");dataSource.setTestWhileIdle(true);dataSource.setValidationQuery("select 'x'");
while (true) { try (DruidPooledConnection connection = dataSource.getConnection()) { System.out.println("获取到连接 = " + connection); } finally { TimeUnit.SECONDS.sleep(5); }}
复制代码
3.2、打印 1 次 获取到连接 = xxx 后断开电脑网络,系统休眠 5 秒后,还能在连接池中拿到连接。
3.3、将 sleep 时间修改为 61 秒之后,在重复 3.2 的步骤,系统在连接池中拿到连接会进行可用性验证。
3.4、以上问题的源码分析
if (testWhileIdle) { final DruidConnectionHolder holder = poolableConnection.holder; long currentTimeMillis = System.currentTimeMillis(); long lastActiveTimeMillis = holder.lastActiveTimeMillis; long lastExecTimeMillis = holder.lastExecTimeMillis; long lastKeepTimeMillis = holder.lastKeepTimeMillis;
if (checkExecuteTime && lastExecTimeMillis != lastActiveTimeMillis) { lastActiveTimeMillis = lastExecTimeMillis; }
if (lastKeepTimeMillis > lastActiveTimeMillis) { lastActiveTimeMillis = lastKeepTimeMillis; } // 连接空闲时间 = 当前时间 - 连接最后一次活跃时间 long idleMillis = currentTimeMillis - lastActiveTimeMillis; // 默认 1 分钟 long timeBetweenEvictionRunsMillis = this.timeBetweenEvictionRunsMillis;
if (timeBetweenEvictionRunsMillis <= 0) { timeBetweenEvictionRunsMillis = DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS; } // 连接空闲时间 >= timeBetweenEvictionRunsMillis(默认1分钟) 才会进行连接的可用性验证操作 if (idleMillis >= timeBetweenEvictionRunsMillis || idleMillis < 0 // unexcepted branch ) { boolean validate = testConnectionInternal(poolableConnection.holder, poolableConnection.conn); if (!validate) { if (LOG.isDebugEnabled()) { LOG.debug("skip not validate connection."); }
discardConnection(poolableConnection.holder); continue; } }}
复制代码
通过上面的源码可以看到触发连接可用性操作的关键代码是:
idleMillis >= timeBetweenEvictionRunsMillis,由于我们没有设置 timeBetweenEvictionRunsMillis 参数的值,默认 1 分钟,
而 idleMillis 是通过 currentTimeMillis - lastActiveTimeMillis 得出,每次获取连接的时间间隔 5 秒小于 60 秒,故不触发检查操作,而设置间隔 61 秒则会触发检查操作。
4、同时配置 timeBetweenEvictionRunsMillis
4.1、测试代码如下:
DruidDataSource dataSource = new DruidDataSource();dataSource.setUrl("jdbc:mysql://ip:port");dataSource.setUsername("name");dataSource.setPassword("password");dataSource.setTestWhileIdle(true);dataSource.setTimeBetweenEvictionRunsMillis(5 * 1000);dataSource.setValidationQuery("select 'x'");
while (true) { try (DruidPooledConnection connection = dataSource.getConnection()) { System.out.println("获取到连接 = " + connection); } finally { TimeUnit.SECONDS.sleep(5); }}
复制代码
如果设置 timeBetweenEvictionRunsMillis 参数为 5 秒,同时测试每隔 5 秒获取一次连接,则连接池在验证可用性的同时,还把 mysqlIdleMillis = currentTimeMillis - lastPacketReceivedTimeMs 的连接进行的丢弃操作,每次连接池返回的都为不同的连接。
4.2、源码如下:
评论