Druid开启keepAlive时shrink方法会导致连接池connections数组连接重复的问题

j91ykkif  于 4个月前  发布在  Druid
关注(0)|答案(1)|浏览(68)

发生问题的原因:

  1. DruidDataSource的connections[]中连接的lastActivetime并不是严格由小到大的。
  2. shrink函数for处理connections数组时,当存在连接的idletime大于minEvictableIdleTimeMillis且小于keepAliveBetweenTimeMillis时,会使此连接不会走代码逻辑中的任何处理分支,即会跳过此连接的处理。
    3.会导致放入evictConnections[]和[]keepAliveConnections数组的连接并不是前removecount个连接。
  3. 因此在system.arraycopy方法里会导致覆盖掉跳过以上处理逻辑的连接。
  4. 在后序if (keepAliveCount > 0) 分支的处理中,放入keepAliveConnections[]的连接又会被put到connections[],从而导致连接池connections[]出现重复连接。

举例来讲,当连接池的connections[] 为{A,B,C,D}时,当A,B的idletime大于minEvictableIdleTimeMillis且小于keepAliveBetweenTimeMillis, C,D的idletime大于minEvictableIdleTimeMillis和keepAliveBetweenTimeMillis。 此时执行shrink时,C,D连接会被放入keepAliveConnections[]中,而在
System.arraycopy(connections, removeCount, connections, 0, poolingCount - removeCount);
Arrays.fill(connections, poolingCount - removeCount, poolingCount, null);
操作中,CD连接会覆盖AB连接,此时connections[]变为{C,D,NULL,NULL}

在后序
if (keepAliveCount > 0) {
for (int i = keepAliveCount - 1; i >= 0; --i) {
boolean putOk = put(holer, 0L);
}
}
会将 C,D连接再次放入connections[],从而导致执行完shrink()后,connections[]成为{C,D,C,D},出现重复连接

gcxthw6b

gcxthw6b1#

另keepAlive中未更新lastActiveTimeMillis,是否会造成idleMillis计算错误,下图示例:

对此有几点疑问:
1:对于连接池中的连接,应保证其idleMillis是从时间久到时间短的顺序。那么需要在每一次将连接put回连接池的时候,去更新这个lastActiveTimeMillis。不过lastActiveTimeMillis的语义并非如此,因为并不合适在keepAlive中更新此时间,或在每次put操作时候更新。对解决此问题,有什么建议么?
2:为什么在shrink中取keepAliveConnections数组是逆序取,逆序放进connections中。看注释有说keep order,对此较为困惑。
期待得到解答!

相关问题