| testOnBorrow | 申请连接时执行validationQuery 配置的探活语句检测连接是否有效。 |
| testWhileIdle | 申请连接的时候检测,如果空闲时间于timeBetweenEvictionRunsMillis ,执 validationQuery 检测连接是否有效 |
| testOnReturn | 归还连接时执 validationQuery 检测连接是否有效。 |
| timeBetweenEvictionRunsMillis | testWhileIdle 的判断依据 |
testOnBorrow 和 testWhileIdle
com.alibaba.druid.pool.DruidDataSource#getConnectionDirect
// 获取连接时检测连接有效性
if (testOnBorrow) {
// 连接检测
boolean validate = testConnectionInternal(poolableConnection.holder, poolableConnection.conn);
if (!validate) {
if (LOG.isDebugEnabled()) {
LOG.debug("skip not validate connection.");
}
discardConnection(poolableConnection.holder);
continue;
}
} else {
// 因为没有做连接检测,需要判断一下
if (poolableConnection.conn.isClosed()) {
discardConnection(poolableConnection.holder); // 传入null,避免重复关闭
continue;
}
// testOnBorrow为false 是testWhileIdle的前提
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;
long timeBetweenEvictionRunsMillis = this.timeBetweenEvictionRunsMillis;
if (timeBetweenEvictionRunsMillis <= 0) {
timeBetweenEvictionRunsMillis = DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS;
}
// 空闲时间大于这个值,进行一下探活
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;
}
}
}
}
testOnReturn
com.alibaba.druid.pool.DruidDataSource#recycle
if (testOnReturn) {
boolean validate = testConnectionInternal(holder, physicalConnection);
if (!validate) {
// 关闭实际连接
JdbcUtils.close(physicalConnection);
destroyCountUpdater.incrementAndGet(this);
lock.lock();
try {
if (holder.active) {
// 活动线程数-1
activeCount--;
// holder活动状态置为false
holder.active = false;
}
closeCount++;
} finally {
lock.unlock();
}
// 由于没有把资源回收到池中,这个holder会被回收掉
return;
}
}
testConnectionInternal
三个参数都需要的探活方法 testConnectionInternal
com.alibaba.druid.pool.DruidAbstractDataSource#testConnectionInternal(com.alibaba.druid.pool.DruidConnectionHolder, java.sql.Connection)
protected boolean testConnectionInternal(DruidConnectionHolder holder, Connection conn) {
if (validConnectionChecker != null) {
//`com.alibaba.druid.pool.DruidDataSource#initValidConnectionChecker` 在 `DruidDataSource#init` 方法中执行
//会根据不同的数据库类型初始化不同的检测器
// 如mysql,如果开启ping方法会直接使用jdbc驱动提供的更轻量级探活机制,否则使用select 1
boolean valid = validConnectionChecker.isValidConnection(conn, validationQuery, validationQueryTimeout);
long currentTimeMillis = System.currentTimeMillis();
if (holder != null) {
// 会更新连接上次可用时间
holder.lastValidTimeMillis = currentTimeMillis;
holder.lastExecTimeMillis = currentTimeMillis;
}
return valid;
}
if (conn.isClosed()) {
return false;
}
if (null == validationQuery) {
return true;
}
Statement stmt = null;
ResultSet rset = null;
try {
stmt = conn.createStatement();
if (getValidationQueryTimeout() > 0) {
stmt.setQueryTimeout(validationQueryTimeout);
}
rset = stmt.executeQuery(validationQuery);
if (!rset.next()) {
return false;
}
} finally {
JdbcUtils.close(rset);
JdbcUtils.close(stmt);
}
}
discardConnection
public void discardConnection(DruidConnectionHolder holder) {
if (holder == null) {
return;
}
Connection conn = holder.getConnection();
if (conn != null) {
JdbcUtils.close(conn);
}
lock.lock();
try {
if (holder.discard) {
return;
}
if (holder.active) {
activeCount--;
holder.active = false;
}
discardCount++;
holder.discard = true;
// 如果可用连接数量小于最小空闲连接数量,唤起创建连接的线程
if (activeCount <= minIdle) {
emptySignal();
}
} finally {
lock.unlock();
}
}
版权声明:本文为abcd2136169原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。