为什么80%的码农都做不了架构师?>>>
连接流转
Druid的连接回收是交给DestroyTask处理的。连接检测间隔可以通过timeBetweenEvictionRunsMillis进行配置,默认是60s。DestoryTask的核心功能有两个:shrink和removeAbandoned。
关键属性
属性名称 |
所属类 |
描述 |
poolingCount |
DruidDataSource |
当前连接池可用数量 |
activeCount |
DruidDataSource |
被使用中的连接数量 |
minIdle |
DruidDataSource |
最小空闲时间 |
minEvictableIdleTimeMillis |
DruidDataSource |
|
maxEvictableIdleTimeMillis |
DruidDataSource |
|
connectTimeMillis |
DruidConnectionHolder |
物理连接创建时间 |
phyTimeoutMillis |
DruidDataSource |
物理连接超时时间 |
lastActiveTimeMillis |
DruidConnectionHolder |
最新活跃时间。刷新时机: 1、执行完sql之后就会更新。 比如executeQuery中调用afterExecute方法 2、keepAlive检查通过之后刷新 3、初始化。创建物理连接时: lastActiveTimeMillis = connectTimeMillis = = System.currentTimeMillis() |
keepAliveCheckCount |
DruidConnectionHolder |
用于统计计数。在shrink中,对连接进行keepAlive检查的时候就会递增 |
testOnReturn |
DruidDataSource |
|
testOnBorrow |
DruidDataSource |
|
testWhileIdle |
DruidDataSource |
|
removeAbandoned |
DruidDataSource |
是否移除已经被丢弃的连接。其实是连接泄露检测。当连接已经被丢弃,但又未关闭释放时,会造成连接 泄露。使用这个状态可以在获取连接的时候,将连接放入到activeConnections中。在destroyTask中会执行 removeAbandoned方法,对activeConnections中的连接进行连接泄露检测。 开启该属性会损失一部分性能。 |
traceEnable |
DruidPooledConnection |
被removeAbandoned的连接设置为false。 |
disable |
DruidPooledConnection |
被removeAbandoned的连接设置为false。 |
shrink
该方法在DestroyThread中执行,主要作用是用于对连接进行检测,丢弃和关闭检测不通过的连接,调整连接池。
- 获取需要检测连接的数量:checkCount = poolingCount - minIdle;
- 是否设置了物理连接的超时时间phyTimoutMills。假如设置了该时间,判断连接时间存活时间是否已经超过phyTimeoutMills,是则放入evictConnections中。
- 空余时间大于minEvictableIdleTimeMillis,并且索引(在连接池中的index)小于checkCount的连接则放入evictConnections;空余时间小于minEvictableIdleTimeMillis的不需要回收
- 空余时间大于minEvictableIdleTimeMillis,并且索引大于checkCount的连接,假若空余时间大于maxEvictableIdleTimeMillis则放入evictConnections,否则放入keepAliveConnections中进行keepAlive检测。
evictConnections中的连接会从connections中移除,并且使用JdbcUtils.close() 关闭连接
对keepAliveConnections中的连接进行连接可用性检测(validateConnection方法进行检查,创建物理连接后也是使用该方法检查连接)。检测通过之后,继续使用该连接(采用的是先移除,检测通过再放入的方式),否则使用JdbcUtils.close() 关闭连接。
由于获取连接后,会将连接从connections中移除:
decrementPoolingCount();
DruidConnectionHolder last=connections[poolingCount];
connections[poolingCount]=null;
当连接使用完之后,在recycle时会检查连接是否还可用(testOnReturn -- 其实这些属性都是体现了数据库连接池的设计和连接的生命阶段。),假如可用的话会刷新lastActiveTimeMillis后放入到connections中(放在尾部,符合尾部最新的原则)
整个连接创建最关键的就是连接在connections中的管理,包括新插入,移除和重新插入。 涉及createTimeMills和lastActiveTimeMillis。这个一定要搞清楚,创建连接时是怎么放进去,shrink时怎么移除,怎么判断,使用完连接之后又是怎么recycle,recycle的时候又是改变了哪些相关的值。
removeAbandoned
连接泄露检测。通过removeAbandoned属性配置是否打开连接泄露检测。
- 获取activeConnectionLock
- 判断连接是否在使用中。pooledConnection.isRunning()
- 连接创建时间是否大于removeAbandonedTimeoutMillis,否则结束处理
- 设置traceEnable为false
- 将连接从activeConnections中移除
- 释放activeConnectionLock
- 标记pooledConnection为disable(需要获取DruidPooledConnection的lock)
- 关闭连接
- 标记为abandoned
- removeAbandonedCount++
开启连接泄露功能会带来一定的性能影响,建议在需要排查问题时才打开次功能