1 关闭连接池
关闭时调用close()方法,主要流程:
- 依旧加锁,判断状态是初始化完成的,且没有关闭,进入关闭流程
- 中断各个线程池
- 从DruidConnectionHolder中获取连接,并依次关闭
- 注销mbean,完成关闭流程,销毁Filter,释放锁
2 StackTrace
在DruidDataSource中单独定义了一个StackTrace,就是在初始化的时候获取了当前线程的StackTrace,目测目的是为了自定义输出调试信息
private String initStackTrace;
...
initStackTrace = Utils.toString(Thread.currentThread().getStackTrace());
3 重启连接池
重启时调用restart()方法,主要流程:
加锁->判断活跃连结数是否为0-> 调用close() ->调用resetStat()
resetStat()重置配置到默认值,设置各个原子计数器为0
connectErrorCountUpdater.set(this, 0);
errorCountUpdater.set(this, 0);
commitCountUpdater.set(this, 0);
rollbackCountUpdater.set(this, 0);
startTransactionCountUpdater.set(this, 0);
cachedPreparedStatementHitCountUpdater.set(this, 0);
closedPreparedStatementCountUpdater.set(this, 0);
preparedStatementCountUpdater.set(this, 0);
transactionHistogram.reset();
cachedPreparedStatementDeleteCountUpdater.set(this, 0);
recycleErrorCountUpdater.set(this, 0);
resetCountUpdater.incrementAndGet(this);
//看起来比init多了几个计数器?
如果有配置变动,调用configFromPropety()重新配置各属性
此时重启便结束了,下一次调用getConnection()的时候,会调用init()重新初始化
4 其他细节
关于几个原子计数器,由于Druid说是为监控而生的连接池,默认是基于内存计数的,所以restart里清空的几个计数器,根据名字就能比较明显地知道是统计各种情况发生的次数的,如:链接错误数,事务提交、回滚数等等
那么之前init中的几个计数器,是做什么的么?
connectionIdSeedUpdater 追了下,主要是生成连接id的,对应到holder中的connectionId,
在DataSource中的getPoolingConnectionInfo(),放到了一个map里,缓存了连接信息
在DruidStatManagerFacade和DruidStatService 中获取了map中的连接信息,供监控控制台使用
dataSource的id本身是自增的,留出来的步长是生成connectionid等根据id的前缀判断属于哪个datasource
使用AtomicLongFieldUpdater的好处是:
因为当需要进行原子限定的属性所属的类会被创建大量的实例对象,如果用AtomicLong每个实例里面都要创建AtomicLong对象,从而多出内存消耗,使用AtomicLongFieldUpdater仅需要在抽象的父类中声明一个静态的更新器,就可以在各个对象中使用了。
网友评论