druid1.0.21版本源码研究之连接回收(分析解决mysql8小时断线)
druid
阿里云计算平台DataWorks(https://help.aliyun.com/document_detail/137663.html) 团队出品,为监控而生的数据库连接池
项目地址:https://gitcode.com/gh_mirrors/druid/druid
免费下载资源
·
首先我想说的是,翻遍百度没有一个可用的解决方案,呵呵..我相信实际解决的人不在少数...
大家众所周知,mysql和druid可谓数据库和数据库连接池中的佼佼者...
第一次用mysql用的还是比较头疼的...
尤其是同时碰上druid...简直是要命了..
换过好几次druid版本,完全没有解决...
github上看wenshao说的,maxEvictableIdleTimeMillis用于解决mysql8小时自动中断,从源码看是有效的.
通过源码,总结一下会出现mysql8小时空闲后中断连接可能出现的情况
1.timeBetweenEvictionRunsMillis+minEvictableIdleTimeMillis>8小时
2.minIdle>0,导致druid会至少保留一个连接,使用1.0.18版本及以上版本不会存在该问题,如果你修改了mysql的wait_timeout,那么可以配置maxEvictableIdleTimeMillis判断可空闲最大时间,即使当前线程数等于minIdle也会强制回收,当然这个回收流程需要timeBetweenEvictionRunsMillis间隔时间后才会检测.
如果是其余问题,请查看druid监控页面是否有sql运行导致锁表
而我遇到的连接池挂掉正是mysql锁表导致的,有个sql锁了系统核心的那张表,所以什么操作都无法进行了
回到正题,看看druid如何执行的回收
druid回收的线程
public class DestroyTask implements Runnable {
@Override
public void run() {
shrink(true);
if (isRemoveAbandoned()) {
removeAbandoned();
}
}
}
接下来的代码也很简单易懂,超过各个参数条件设置的一律回收,有些参数api中没有提到,但是同样可以配置.
public void shrink(boolean checkTime) {
final List<DruidConnectionHolder> evictList = new ArrayList<DruidConnectionHolder>();//待回收的连接集合
try {
lock.lockInterruptibly();
} catch (InterruptedException e) {
return;
}
try {
final int checkCount = poolingCount - minIdle;//连接池连接数-最小保留连接数
final long currentTimeMillis = System.currentTimeMillis();
for (int i = 0; i < poolingCount; ++i) {
DruidConnectionHolder connection = connections[i];
if (checkTime) {//上一个代码可以看到,传递为true
if (phyTimeoutMillis > 0) {
long phyConnectTimeMillis = currentTimeMillis - connection.getTimeMillis();//此处直接用当前时间-获取连接的时间
if (phyConnectTimeMillis > phyTimeoutMillis) {//连接不管是否空闲,存活phyTimeoutMillis后强制回收
evictList.add(connection);
continue;
}
}
long idleMillis = currentTimeMillis - connection.getLastActiveTimeMillis();//此处系统时间-该连接最后一次活跃时间,即访问数据库时间
if (idleMillis < minEvictableIdleTimeMillis) {//此处是break无问题,空闲连接从0开始排,取从最后开始取
break;
}
if (checkTime && i < checkCount) {//checkTime为true,此处验证上方的最小连接数,释放到最小连接后不再释放
evictList.add(connection);
} else if (idleMillis > maxEvictableIdleTimeMillis) {//此处验证最大存活时间,无视最小连接数强制回收
evictList.add(connection);
}
} else {
if (i < checkCount) {
evictList.add(connection);
} else {
break;
}
}
}
int removeCount = evictList.size();
if (removeCount > 0) {//此处重新复制有效连接到连接池数组中
System.arraycopy(connections, removeCount, connections, 0, poolingCount - removeCount);
Arrays.fill(connections, poolingCount - removeCount, poolingCount, null);
poolingCount -= removeCount;
}
} finally {
lock.unlock();
}
for (DruidConnectionHolder item : evictList) {//回收连接
Connection connection = item.getConnection();
JdbcUtils.close(connection);
destroyCount.incrementAndGet();
}
}
GitHub 加速计划 / druid / druid
27.83 K
8.56 K
下载
阿里云计算平台DataWorks(https://help.aliyun.com/document_detail/137663.html) 团队出品,为监控而生的数据库连接池
最近提交(Master分支:3 个月前 )
f060c270 - 8 天前
1613a765
* Improve gaussdb ddl parser
* fix temp table 10 天前
更多推荐
已为社区贡献2条内容
所有评论(0)