DBCP2 - 何时从池中删除空闲连接

Posted

技术标签:

【中文标题】DBCP2 - 何时从池中删除空闲连接【英文标题】:DBCP2 - When are Idle connections removed from the Pool 【发布时间】:2016-12-05 17:19:37 【问题描述】:

在配置 DBCP2 池时,基于 documentation 我注意到 - 有一个名为 timeBetweenEvictionRunsMillis 的配置被描述为:

空闲对象运行之间休眠的毫秒数 驱逐线程。当为非正数时,没有空闲的对象驱逐线程将 运行。

其默认值为-1

这是否意味着 evictor 线程永远不会在默认配置中运行?那么配置参数maxIdle 是如何强制执行的——如果空闲连接的数量大于maxIdle,则池必须驱逐空闲连接。

让我感到很困惑的是,默认配置是永远不会驱逐空闲连接。

还有另一个配置softMiniEvictableIdleTimeMillis 似乎在timeBetweenEvictionRunsMillis 之上发挥了一些作用。

在这方面的任何澄清都会有很大的帮助。

暂时,我正在配置池,如下所示 - 因为我的目标是在我的池中没有任何空闲连接太久(这是需要的,因为我们使用的是 AWS RDS 并且似乎有 a weird issue 与我们经常遇到的)

    BasicDataSource dataSource = new BasicDataSource();
    dataSource.setDriverClassName("com.mysql.jdbc.Driver");
    dataSource.setUrl(properties.getProperty("app.mysql.url"));
    dataSource.setUsername(properties.getProperty("app.mysql.username"));
    dataSource.setPassword(properties.getProperty("app.mysql.password"));
    dataSource.setMaxIdle(20);
    dataSource.setMaxWaitMillis(20000); //wait 10 seconds to get new connection
    dataSource.setMaxTotal(200);
    dataSource.setMinIdle(0);
    dataSource.setInitialSize(10);
    dataSource.setTestOnBorrow(true);
    dataSource.setValidationQuery("select 1");
    dataSource.setValidationQueryTimeout(10); //The value is in seconds

    dataSource.setTimeBetweenEvictionRunsMillis(600000); // 10 minutes wait to run evictor process
    dataSource.setSoftMinEvictableIdleTimeMillis(600000); // 10 minutes wait to run evictor process
    dataSource.setMinEvictableIdleTimeMillis(60000); // 60 seconds to wait before idle connection is evicted
    dataSource.setMaxConnLifetimeMillis(600000); // 10 minutes is max life time
    dataSource.setNumTestsPerEvictionRun(10);

【问题讨论】:

【参考方案1】:

是的,驱逐线程默认不会运行。原因是maxIdlemaxTotal的值默认是一样的,也就是说不会有立即关闭的连接,也不需要驱逐空闲的连接。因此,池只是通过不运行无用的线程来节省一些资源。

但是当你改变maxIdle并使其低于maxTotal而不启动evictor线程时,并不意味着你的连接不会被关闭。这意味着它们将在释放后立即关闭,没有延迟,直到它们的数量不下降到maxIdle

然后minEvictableIdleTimeMillissoftMinEvictableIdleTimeMillis 来玩(小心,文档中有错字,它是...MinEvictalbe...,而不是...MiniEvictable...)。它们之间的区别在于前者不尊重minIdle,而后者则尊重。考虑到 softMinEvictableIdleTimeMillis 仅在 minEvictableIdleTimeMillis 已过时才被检查,这有点棘手。

假设我们有minEvictableIdleTimeMillis=10000softMinEvictableIdleTimeMillis=-1(默认情况下)。在这种情况下,空闲连接将在池中保留不超过 10 秒。即使连接数不超过minIdle,也会被关闭。如果导致连接数低于minIdle的丢弃,将立即创建一个新连接。

现在,假设我们有minEvictableIdleTimeMillis=10000softMinEvictableIdleTimeMillis=30000。在这种情况下,在检查 minEvictableIdleTimeMillis 并检测到超出之后的空闲连接将另外检查 softMinEvictableIdleTimeMillis。如果空闲时间超过它,连接将被关闭。否则,它将保留在池中,直到对 minEvictableIdleTimeMillis 进行下一次肯定检查。

最终,maxTotalmaxIdle 之间的连接将立即关闭,maxIdleminIdle 之间的连接在 minEvictableIdleTimeMillis 之后关闭,minIdle0 之间的连接在 softMinEvictableIdleTimeMillis 之后关闭并立即重新开放。给予或接受驱逐检查期。

使用您的配置,当池大于 20 时,您将立即关闭所有连接。这 20 个连接的生存时间为 10 到 20 分钟(即使空闲),因为您有 10 分钟的 EvictableIdleTimeMillisTimeBetweenEvictionRunsMillis 10 分钟。

我还想提一下maxIdlemaxTotal 之间存在较大差距的潜在问题。如果您预计maxIdle 会经常被超过,最好增加它。否则,您将面临不断的连接打开和关闭,这将对您的数据库(因为建立新的数据库连接是相对繁重的操作)和应用服务器网络基础设施(因为关闭的连接将挂在 TIME_WAIT 状态,耗尽您的网络端口)造成额外压力池)。

【讨论】:

感谢您提供详细信息。在 10-20 分钟窗口期间的那些空闲连接 - 它们会被连接池重用吗?我的猜测是它们将被重用。在您的第二个示例中,当您说If the idle time exceeds it...时,您的意思是它是否超过 10000 + 30000? @Wand Marker,不客气。关于重用连接,如果我正确理解了这个问题,当然池会在需要它们时重用它们,并且“空闲计时器”将重置。 是的,这就是我的意思。再次感谢大家的帮助! 另一个提示:小心使用大号timeBetweenEvictionRunsMillis。它将增加连接在池中的时间。在几秒钟而不是十分钟内检查一次连接并没有什么危险。开销是微不足道的,它只是一个非阻塞的添加和比较几个数字。检查周期越短,您可以越精确地调整连接寿命。 我要改成1分钟吗?

以上是关于DBCP2 - 何时从池中删除空闲连接的主要内容,如果未能解决你的问题,请参考以下文章

在 Wildfly-17 中的数据库故障转移期间回滚事务时,数据库连接不会从池中删除

在从池中获取连接之前经过的超时时间

[转]超时时间已到。超时时间已到,但是尚未从池中获取连接。出现这种情况可能是因为所有池连接均在使用,并且达到了最大池大小。

超时时间已到。超时时间已到,但是尚未从池中获取连接。出现这种情况可能是因为所有池连接均在使用,并且达到了最大池大小。

连接字符串中Min Pool Size的理解是错误,超时时间已到,但是尚未从池中获取连接。出现这种情况可能是因为所有池连接均在使用,并且达到了最大池大小。

was连接池怎么看