先看一张图就大概了解了duriad连接池的做法:
Druid的连接回收是交给DestroyTask处理的。连接检测间隔可以通过timeBetweenEvictionRunsMillis进行配置,默认是60s。DestoryTask的核心功能有两个:shrink和removeAbandoned。
关键属性
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();DruidConnectionHolderlast=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++
开启连接泄露功能会带来一定的性能影响,建议在需要排查问题时才打开次功能