这篇文章尝试回答一下秦老师提出的问题,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);}
复制代码
评论