minEvictableIdleTimeMillis=100000 setMaxEvictableIdleTimeMillis=1000L 60L 60L * 7 keepAliveBetweenTimeMillis=120000 minIdle=2 timeBetweenEvictionRunsMillis=70000 validationQuery=select 1 keepAlive=true
2.测试代码如下: DruidDataSource druidDataSource = new DruidDataSource();
druidDataSource.setUsername("");
druidDataSource.setPassword("");
druidDataSource.setUrl("jdbc:mysql://192.168.253.129:3306/user?characterEncoding=utf8&autoReconnect=true&zeroDateTimeBehavior=convertToNull&serverTimezone=UTC&useSSL=false&allowMultiQueries=true");
druidDataSource.setValidationQuery("select 1");
druidDataSource.setMinEvictableIdleTimeMillis(100000);
druidDataSource.setMaxEvictableIdleTimeMillis(DEFAULT_MAX_EVICTABLE_IDLE_TIME_MILLIS);
druidDataSource.setKeepAliveBetweenTimeMillis(120000);
druidDataSource.setMinIdle(2);
druidDataSource.setTimeBetweenEvictionRunsMillis(70000);
druidDataSource.setKeepAlive(true);
DruidPooledConnection connection1 = druidDataSource.getConnection();
DruidPooledConnection connection2 = druidDataSource.getConnection();
connection2.close();
Thread.sleep(95000);
connection1.close();
Thread.sleep(140000);
DruidPooledConnection connection3 = druidDataSource.getConnection();
DruidPooledConnection connection4 = druidDataSource.getConnection();
System.out.println(connection3.getConnectionHolder() == connection4.getConnectionHolder());
connection3.close();
connection4.close();
3.运行结果:
4.原因分析:
问题出现在DestoryTask的shrink函数中。 时间点70000ms时:connections[connection2],connection2的空闲时间均小于minEvictableIdleTimeMillis和keepAliveBetweenTimeMillis跳过
时间点95000时,connection1返还连接池,此时connections[connection2,connection1],connections中的元素空闲时间是递减的
时间点140000ms时,connection2因为空闲时间大于120000会加到keepConnections数组中,后返还,返还时未修改lastActiveTimeMillis,此时connections[connection1,connection2],connection2的空闲时间比connection1的要大
时间点210000ms时,connections1因为空闲时间大于100000,但由于设置minidel=2会跳过shrink中所有if代码块,connections2由于空闲时间大于120000,会加入keepconnection中。进而导致connections会有两个相同的holder
5.总结:1.2.6版本中限制timeBetweenEvictionRunsMillis小于keepAliveBetweenTimeMillis并不能解决问题。该问题出现的原因还是shrink函数中connections拷贝的bug,希望官方能解决这个bug,可参考pullrequest:https://github.com/alibaba/druid/pull/4218
另一方面keepConnection放回connections未修改lastActiveTimeMills,会导致connections的空闲时间不是递减的。
@wenshao