写点什么

druid 源码阅读(九)Druid removeAbandoned 参数

  • 2022 年 5 月 18 日
  • 本文字数:1516 字

    阅读完需:约 5 分钟

1、设置

removeAbandoned 参数默认为 false,可以通过 DruidDataSource.setRemoveAbandoned(true)开启

2、含义

防止连接泄露,在一个连接长时间未被关闭时,会主动回收该连接,默认关闭,官方不推荐在生产环境开启。

3、工作原理

查看关于 removeAbandoned 的相关测试案例 TestRemoveAbandoned:

    protected void setUp() throws Exception {        driver = new MockDriver();
dataSource = new DruidDataSource(); dataSource.setUrl("jdbc:mock:xxx"); dataSource.setDriver(driver); dataSource.setInitialSize(1); dataSource.setMaxActive(2); dataSource.setMaxIdle(2); dataSource.setMinIdle(1); dataSource.setMinEvictableIdleTimeMillis(300 * 1000); // 300 / 10 dataSource.setTimeBetweenEvictionRunsMillis(10); // 180 / 10 dataSource.setRemoveAbandoned(true); dataSource.setRemoveAbandonedTimeoutMillis(10); dataSource.setTestWhileIdle(true); dataSource.setTestOnBorrow(false); dataSource.setValidationQuery("SELECT 1"); dataSource.setFilters("stat"); dataSource.setLogAbandoned(true);
Assert.assertEquals(0, DruidDataSourceStatManager.getInstance().getDataSourceList().size()); }
public void test_removeAbandoned() throws Exception { Connection conn = dataSource.getConnection(); Assert.assertEquals(1, dataSource.getActiveCount()); Assert.assertEquals(0, dataSource.getPoolingCount());
// 超时之后,连接自动关闭 Thread.sleep(100); Assert.assertTrue(conn.isClosed());
Assert.assertEquals(1, dataSource.getRemoveAbandonedCount()); Assert.assertEquals(0, dataSource.getActiveCount()); Assert.assertEquals(1, dataSource.getPoolingCount()); }
复制代码

从测试案例中可以发现,设置了 removeAbandoned 后,如果只获取连接,但是不主动关闭的话,就可以触发 Druid 的主动关闭连接的机制。

我们全局搜索一下 removeAbandoned,发现主要有这几个地方调用了这个参数:

1、建立连接时,如果开启了这个参数,会记录调用线程栈,并把这个连接放入 activeConnections 这个 map 中;

2、在连接使用前将当前连接 running 参数置为 true;

3、在连接使用后记录当前时间到 lastActiveTimeMillis,将 running 参数置为 false;

4、在 DestroyTask 线程中检查连接是否长时间未被关闭,如果是的话就关闭连接,整个过程需要加锁;

//连接是否使用状态if (pooledConnection.isRunning()) {    continue;}long timeMillis = (currrentNanos - pooledConnection.getConnectedTimeNano()) / (1000 * 1000);//连接空闲时间大于设置的参数removeAbandonedTimeoutMillis,关闭连接if (timeMillis >= removeAbandonedTimeoutMillis) {    iter.remove();    pooledConnection.setTraceEnable(false);    abandonedList.add(pooledConnection);}
复制代码

5、在关闭连接的时候通过判断 removeAbandoned 决定是否要使用锁保证线程安全,因为开始 removeAbandoned 后,一个连接可能会被使用连接的线程关闭,也可能会被 DestroyTask 线程关闭,加锁保证线程安全。

4、总结

通过上面的分析,我们发现,以上在开启 removeAbandoned 后,很多对连接的操作就要增加锁来保证线程安全性,用效率换取了线程的安全性。而且现在的大多数框架都会保证连接在使用后得到释放,这个参数就没有打开的必要了,所以官方才不推荐生产环境打开这个参数。

用户头像

还未添加个人签名 2021.05.30 加入

还未添加个人简介

评论

发布
暂无评论
druid 源码阅读(九)Druid removeAbandoned参数_5月月更_爱晒太阳的大白_InfoQ写作社区