这篇文章尝试回答一下秦老师提出的问题,druid keepAlive 实现方式?
查找思路:
总共有两个相关参数:
dataSource.setKeepAlive(true);
dataSource.setKeepAliveBetweenTimeMillis(100000);
复制代码
keepAlive(默认关闭)功能:
一、初始化连接池时会填充到 minIdle 数量
if (keepAlive) {
// async fill to minIdle
if (createScheduler != null) {
for (int i = 0; i < minIdle; ++i) {
submitCreateTask(true);
}
} else {
this.emptySignal();
}
}
复制代码
追到这个地方:com.alibaba.druid.pool.DruidDataSource.CreateConnectionTask#runInternal
// 必须存在线程等待,才创建连接
if (poolingCount >= notEmptyWaitThreadCount //
&& (!(keepAlive && activeCount + poolingCount < minIdle)) // 在keepAlive场景不能放弃创建
&& (!initTask) // 线程池初始化时的任务不能放弃创建
&& !isFailContinuous() // failContinuous时不能放弃创建,否则会无法创建线程
&& !isOnFatalError() // onFatalError时不能放弃创建,否则会无法创建线程
) {
clearCreateTask(taskId);
return;
}
复制代码
和这个地方:com.alibaba.druid.pool.DruidDataSource.CreateConnectionThread#run
if (emptyWait) {
// 必须存在线程等待,才创建连接
if (poolingCount >= notEmptyWaitThreadCount //
&& (!(keepAlive && activeCount + poolingCount < minIdle))
&& !isFailContinuous()
) {
empty.await();
}
// 防止创建超过maxActive数量的连接
if (activeCount + poolingCount >= maxActive) {
empty.await();
continue;
}
}
复制代码
这几个地方代表一个意思:初始化连接池和新建连接的逻辑中,会把连接数填充到 minIdle 数量。
二、连接池中的 minIdle 数量以内的连接,空闲时间超过 minEvictableIdleTimeMillis,则会执行 keepAlive 操作,打开会一直保持 minIdle 的数量值;
com.alibaba.druid.pool.DruidDataSource.DestroyTask#run
public void run() {
shrink(true, keepAlive);
if (isRemoveAbandoned()) {
removeAbandoned();
}
}
复制代码
对应到这里:com.alibaba.druid.pool.DruidDataSource#shrink(boolean, boolean)
有两个地方用 keepalive 判断。
1、如果 idle 时间大于探活时间,
if (keepAlive && idleMillis >= keepAliveBetweenTimeMillis) {
keepAliveConnections[keepAliveCount++] = connection;
}
复制代码
2、如果当前连接数小于 minIdle,进行连接数的补充。
if (keepAlive && poolingCount + activeCount < minIdle) {
needFill = true;
}
复制代码
最终遍历并探活 keepAliveConnections 的代码在这里:
if (keepAliveCount > 0) {
// keep order
for (int i = keepAliveCount - 1; i >= 0; --i) {
DruidConnectionHolder holer = keepAliveConnections[i];
Connection connection = holer.getConnection();
holer.incrementKeepAliveCheckCount();
boolean validate = false;
try {
this.validateConnection(connection);
validate = true;
} catch (Throwable error) {
if (LOG.isDebugEnabled()) {
LOG.debug("keepAliveErr", error);
}
// skip
}
boolean discard = !validate;
if (validate) {
holer.lastKeepTimeMillis = System.currentTimeMillis();
boolean putOk = put(holer, 0L, true);
if (!putOk) {
discard = true;
}
}
if (discard) {
try {
connection.close();
} catch (Exception e) {
// skip
}
lock.lock();
try {
discardCount++;
if (activeCount + poolingCount <= minIdle) {
emptySignal();
}
} finally {
lock.unlock();
}
}
}
this.getDataSourceStat().addKeepAliveCheckCount(keepAliveCount);
Arrays.fill(keepAliveConnections, null);
}
复制代码
评论