销毁连接分析
在创建连接的init()
方法,注意到创建了线程DestroyConnectionThread
用来销毁连接的,线程循环是通过timeBetweenEvictionRunsMillis
参数来设置连接检查的时间间隔。
public void run() {
//计数器减一
initedLatch.countDown();
for (;;) {
// 从前面开始删除
try {
//如果连接池未关闭
if (closed || closing) {
break;
}
//设置时间间隔休眠
if (timeBetweenEvictionRunsMillis > 0) {
Thread.sleep(timeBetweenEvictionRunsMillis);
} else {
Thread.sleep(1000);
}
//如果发生中断异常则退出
if (Thread.interrupted()) {
break;
}
//运行销毁任务
destroyTask.run();
} catch (InterruptedException e) {
break;
}
}
}
DestroyTask
销毁任务类,通过DestroyConnectionThread
线程直接调用,一旦有自定义销毁任务时,才会变为线程执行。
@Override
public void run() {
//检查连接
shrink(true, keepAlive);
//移出废弃的连接
if (isRemoveAbandoned()) {
removeAbandoned();
}
}
shrink
该方法主要是检查连接,并销毁连接。
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 {
//如果还未进行初始化,则进行init()
if (!inited) {
return;
}
//剩余空闲连接数 = 连接池中连接数- 最小空闲连接数
final int checkCount = poolingCount - minIdle;
final long currentTimeMillis = System.currentTimeMillis();
for (int i = 0; i < poolingCount; ++i) {
//从连接池中拿连接
DruidConnectionHolder connection = connections[i];
//(如果发生致命错误或者致命错误次数大于0)&& 最后致命错误时间大于当前连接的连接时间
if ((onFatalError || fatalErrorIncrement > 0) && (lastFatalErrorTimeMillis > connection.connectTimeMillis)) {
//设置为存活连接
keepAliveConnections[keepAliveCount++] = connection;
continue;
}
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;
}
//空闲时间 >= 最小存活时间,将连接放入销毁池中
if (idleMillis >= minEvictableIdleTimeMillis) {
if (checkTime && i < checkCount) {
evictConnections[evictCount++] = connection;
continue;
} else if (idleMillis > maxEvictableIdleTimeMillis) {
evictConnections[evictCount++] = connection;
continue;
}
}
//开启保活机制 && 空闲时间 >= 连接保活时间,将连接放入存活池中。
if (keepAlive && idleMillis >= keepAliveBetweenTimeMillis) {
keepAliveConnections[keepAliveCount++] = connection;
}
//如果未开启检查,则仅留下最小空闲连接。
} else {
if (i < checkCount) {
evictConnections[evictCount++] = connection;
} else {
break;
}
}
}
//删除数量 = 销毁连接数量+ 活跃连接数量
int removeCount = evictCount + keepAliveCount;
if (removeCount > 0) {
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);
}
Arrays.fill(evictConnections, null);
}
//如果活跃连接数量 >0 ,则对连接进行校验
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);
}
//如果需要创建连接,则释放锁进行创建
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();
}
}
}