DruidDataSource
initialSize minIdle(最小值) maxActive(最大值) poolingCount(池内的) maxActive(借出的)
一般来说poolingCount+maxActive和minIdle和maxActive比较,以前有个maxIdle,现在不用了,导致有些和minIdle比较的逻辑有问题
我们用connections这个数组,poolingCount就是现在的位置,总是在尾部取放,栈结构
Lock,notEmpty和empty
DruidPooledConnection用于对外使用,DruidConnectionHolder(内部两套参数,default用于连接放回的复原,underlying用于记录连接的当前状态)是内部使用
create:系统属性配置
init:
1 创建initialSize个连接,Driver.connect创建连接,有filters则代理一层,每个连接根据配置初始化连接的autoCommit等,执行初始sqls,variables或global variables,validate后放入
2 CreateConnectionThread和DestroyConnectionThread创建
3 若keepAlive,empty.signal
getConnection:循环获取连接
1 尝试获取:pollLast(maxWait)或takeLast,循环等待,若现在无可用的,empty.signal,notEmpty.await,有则直接取
2 activeCount++ 且holder.active, DruidPooledConnection进行wrap
3 testOnBorrow 或testWhileIdle
testWhileIdle:通过上一次放回(lastActive)和上一次keepAlive(lastKeep)的较大值获取空闲时间与timeBetweenEvictionRunsMillis比较决定是否校验
校验方式:普通validate+若为mysql则检测上次收到的packet是否timeBetweenEvictionRunsMillis(1min)内
校验不通过,抛弃连接(若activeCount<=minIdle,empty.signal),重新获取连接(在循环中)
4 若removeAbandoned,连接需记录在activeConnections内
关闭连接
disable/closed/holder/conn都置空,若此连接未abandoned, 则recycle
recycle流程:
1 没有完成事务就close,rollback
2 重置复原连接状态,holder内缓存的statement关闭
3 testOnReturn:validate+上次packet时间检查,不通过则关闭连接
4 放回
CreateConnectionThread:循环创建连接,一般在empty上等待
1 poolingCount=0 且最近一次创建连接存在createError 且两次创建连接之间不存在discard连接,此次不等待
2 poolingCount>=notEmptyWaitThreadCount(当前等待获取连接线程数) 且非连续失败 且非在keepAlive情况下activeCount + poolingCount < minIdle,此次等待
3 非上述两情况或2等待唤醒后判断,若activeCount + poolingCount >= maxActive,等待并在唤醒后从1开始判断
4 不等或等待唤醒后创建连接(初始化+validate),创建后放入,poolingCount >= maxActive放入失败,notEmpty.signal
注意:创建连接时RuntimeException或多次SQLException则认定连续失败,创建连接成功清除连续失败
DestroyConnectionThread: 循环运行,每timeBetweenEvictionRunsMillis运行一次
1 shrink
在poolingCount内针对每个连接
1.1 当前fatalError或当前和上次shrink之间出现过fatalError 且 此连接创建时间早于上次fatalError,此连接强制keepAlive(不判断keepAlive标识)且跳过当前连接
1.2 否则 空闲时间小于minEvictableIdleTimeMillis和keepAliveBetweenTimeMillis则跳出循环判断
1.3 空闲时间大于minEvictableIdleTimeMillis
1.3.1 当前在前(poolingCount-minIdle内),evict且跳过当前连接
1.3.2 空闲时间大于maxEvictableIdleTimeMillis,evict且跳过当前连接
1.4 keepAlive 且 空闲时间大于keepAliveBetweenTimeMillis,keepAlive
1.5 前面都是evict或keepAlive的,这两部分取出后connections前移,evict的干掉,keepAlive进行validate,成功则放回,失败则丢弃(activeCount + poolingCount <= minIdle,empty.signal)
2 若开启removeAbandoned,取activeConnections,找出借出超过removeAbandonedTimeoutMillis的连接,关闭连接,设置为abandoned
注意:连接完全可能低于minIdle, 比较1.1.16版本和1.2.5,1.2.5版本在shrink时若开启keepAlive,试图在总连接低于minIdle时empty.signal