// 连接池瘦身
public void shrink(boolean checkTime, boolean keepAlive) {
try {
lock.lockInterruptibly();
} catch (InterruptedException e) {
return;
}
boolean needFill = false;
int evictCount = 0;
int keepAliveCount = 0;
int fatalErrorIncrement = fatalErrorCount - fatalErrorCountLastShrink;
fatalErrorCountLastShrink = fatalErrorCount;
try {
if (!inited) {
return;
}
// 根据 poolingCount 和 minIdle 计算出 evictCheck(丢弃检查) 的范围
final int checkCount = poolingCount - minIdle;
final long currentTimeMillis = System.currentTimeMillis();
// 开始遍历连接池里闲置的连接
for (int i = 0; i < poolingCount; ++i) {
DruidConnectionHolder connection = connections[i];
if ((onFatalError || fatalErrorIncrement > 0) && (lastFatalErrorTimeMillis > connection.connectTimeMillis)) {
keepAliveConnections[keepAliveCount++] = connection;
continue;
}
// 除非手动调用,不然经过主流程4触发,一般为 true
if (checkTime) {
// 默认不启用,忽略
if (phyTimeoutMillis > 0) {
long phyConnectTimeMillis = currentTimeMillis - connection.connectTimeMillis;
if (phyConnectTimeMillis > phyTimeoutMillis) {
evictConnections[evictCount++] = connection;
continue;
}
}
// 计算闲置时间
long idleMillis = currentTimeMillis - connection.lastActiveTimeMillis;
// 如果闲置时间达不到检测&瘦身的阈值,则不处理
if (idleMillis < minEvictableIdleTimeMillis
&& idleMillis < keepAliveBetweenTimeMillis
) {
break;
}
// 达到需要丢弃的阈值时,则判断连接下标是否在 evictCheck 范围,若在,则视为“可以丢弃的对象”放入e victConnections 数组
if (idleMillis >= minEvictableIdleTimeMillis) {
if (checkTime && i < checkCount) {
evictConnections[evictCount++] = connection;
continue;
} else if (idleMillis > maxEvictableIdleTimeMillis) {
evictConnections[evictCount++] = connection;
continue;
}
}
// 如果上面的条件均没有命中,如果 keepAlive 为 true,则判断是不是超过了闲置连接检查其活性的频次阈值(即由 keepAliveBetweenTimeMillis 控制)
if (keepAlive && idleMillis >= keepAliveBetweenTimeMillis) {
// 满足条件则视为“需要检测活性的对象”,放入 keepAliveConnections 数组
keepAliveConnections[keepAliveCount++] = connection;
}
} else {
if (i < checkCount) {
evictConnections[evictCount++] = connection;
} else {
break;
}
}
}
// 这一批需要移除特殊处理的连接总数
int removeCount = evictCount + keepAliveCount;
if (removeCount > 0) {
// 根据当前移除的元素,把剩余的元素移动至数组首部(参考流程4.1)
System.arraycopy(connections, removeCount, connections, 0, poolingCount - removeCount);
// 剩余位置清空
Arrays.fill(connections, poolingCount - removeCount, poolingCount, null);
poolingCount -= removeCount;
}
keepAliveCheckCount += keepAliveCount;
if (keepAlive && poolingCount + activeCount < minIdle) {
needFill = true;
}
} finally {
lock.unlock();
}
// 如果需要丢弃的连接数量大于 0
if (evictCount > 0) {
for (int i = 0; i < evictCount; ++i) {
DruidConnectionHolder item = evictConnections[i];
Connection connection = item.getConnection();
// 直接关闭连接(这里是直接关闭驱动连接,不再放回池子)
JdbcUtils.close(connection);
destroyCountUpdater.incrementAndGet(this);
}
// 将 evictConnections 数组重新置空(方便下次使用)
Arrays.fill(evictConnections, null);
}
// 检测那些需要判活的连接数
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) {
// 放不进去池子(说明已经达到连接池最大连接数阈值 maxActive),则视为可以“直接抛弃”的连接
discard = true;
}
}
if (discard) {
try {
// 如果可以抛弃,则直接关闭连接(直接调用驱动的 close)
connection.close();
} catch (Exception e) {
// skip
}
lock.lock();
try {
// 抛弃连接数累加
discardCount++;
if (activeCount + poolingCount <= minIdle) {
// 唤起主流程3追加连接对象
emptySignal();
}
} finally {
lock.unlock();
}
}
}
this.getDataSourceStat().addKeepAliveCheckCount(keepAliveCount);
// 将 keepAliveConnections 数组重新置空(方便下次使用)
Arrays.fill(keepAliveConnections, null);
}
if (needFill) {
lock.lock();
try {
int fillCount = minIdle - (activeCount + poolingCount + createTaskCount);
for (int i = 0; i < fillCount; ++i) {
emptySignal();
}
} finally {
lock.unlock();
}
} else if (onFatalError || fatalErrorIncrement > 0) {
lock.lock();
try {
emptySignal();
} finally {
lock.unlock();
}
}
}
// 上面检测通过,再次通过该方法重新把连接放入池子
private boolean put(DruidConnectionHolder holder, long createTaskId, boolean checkExists) {
lock.lock();
try {
if (this.closing || this.closed) {
return false;
}
// 若池子内闲置连接数超过 maxActive,则无法继续添加新的连接进来,返回 false
if (poolingCount >= maxActive) {
if (createScheduler != null) {
clearCreateTask(createTaskId);
}
return false;
}
if (checkExists) {
for (int i = 0; i < poolingCount; i++) {
if (connections[i] == holder) {
return false;
}
}
}
// 否则直接把此连接对象放入连接池队尾
connections[poolingCount] = holder;
incrementPoolingCount();
if (poolingCount > poolingPeak) {
poolingPeak = poolingCount;
poolingPeakTime = System.currentTimeMillis();
}
// 唤起那些因获取不到可用连接而陷入阻塞状态的业务线程一次
notEmpty.signal();
notEmptySignalCount++;
// 不启用该模式,忽略
if (createScheduler != null) {
clearCreateTask(createTaskId);
if (poolingCount + createTaskCount < notEmptyWaitThreadCount //
&& activeCount + poolingCount + createTaskCount < maxActive) {
emptySignal();
}
}
} finally {
lock.unlock();
}
return true;
}