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】:是的,驱逐线程默认不会运行。原因是maxIdle
和maxTotal
的值默认是一样的,也就是说不会有立即关闭的连接,也不需要驱逐空闲的连接。因此,池只是通过不运行无用的线程来节省一些资源。
但是当你改变maxIdle
并使其低于maxTotal
而不启动evictor线程时,并不意味着你的连接不会被关闭。这意味着它们将在释放后立即关闭,没有延迟,直到它们的数量不下降到maxIdle
。
然后minEvictableIdleTimeMillis
和softMinEvictableIdleTimeMillis
来玩(小心,文档中有错字,它是...MinEvictalbe...
,而不是...MiniEvictable...
)。它们之间的区别在于前者不尊重minIdle
,而后者则尊重。考虑到 softMinEvictableIdleTimeMillis
仅在 minEvictableIdleTimeMillis
已过时才被检查,这有点棘手。
假设我们有minEvictableIdleTimeMillis=10000
和softMinEvictableIdleTimeMillis=-1
(默认情况下)。在这种情况下,空闲连接将在池中保留不超过 10 秒。即使连接数不超过minIdle
,也会被关闭。如果导致连接数低于minIdle
的丢弃,将立即创建一个新连接。
现在,假设我们有minEvictableIdleTimeMillis=10000
和softMinEvictableIdleTimeMillis=30000
。在这种情况下,在检查 minEvictableIdleTimeMillis
并检测到超出之后的空闲连接将另外检查 softMinEvictableIdleTimeMillis
。如果空闲时间超过它,连接将被关闭。否则,它将保留在池中,直到对 minEvictableIdleTimeMillis
进行下一次肯定检查。
最终,maxTotal
和 maxIdle
之间的连接将立即关闭,maxIdle
和 minIdle
之间的连接在 minEvictableIdleTimeMillis
之后关闭,minIdle
和 0
之间的连接在 softMinEvictableIdleTimeMillis
之后关闭并立即重新开放。给予或接受驱逐检查期。
使用您的配置,当池大于 20 时,您将立即关闭所有连接。这 20 个连接的生存时间为 10 到 20 分钟(即使空闲),因为您有 10 分钟的 EvictableIdleTimeMillis
加TimeBetweenEvictionRunsMillis
10 分钟。
我还想提一下maxIdle
和maxTotal
之间存在较大差距的潜在问题。如果您预计maxIdle
会经常被超过,最好增加它。否则,您将面临不断的连接打开和关闭,这将对您的数据库(因为建立新的数据库连接是相对繁重的操作)和应用服务器网络基础设施(因为关闭的连接将挂在 TIME_WAIT 状态,耗尽您的网络端口)造成额外压力池)。
【讨论】:
感谢您提供详细信息。在 10-20 分钟窗口期间的那些空闲连接 - 它们会被连接池重用吗?我的猜测是它们将被重用。在您的第二个示例中,当您说If the idle time exceeds it
...时,您的意思是它是否超过 10000 + 30000?
@Wand Marker,不客气。关于重用连接,如果我正确理解了这个问题,当然池会在需要它们时重用它们,并且“空闲计时器”将重置。
是的,这就是我的意思。再次感谢大家的帮助!
另一个提示:小心使用大号timeBetweenEvictionRunsMillis
。它将增加连接在池中的时间。在几秒钟而不是十分钟内检查一次连接并没有什么危险。开销是微不足道的,它只是一个非阻塞的添加和比较几个数字。检查周期越短,您可以越精确地调整连接寿命。
我要改成1分钟吗?以上是关于DBCP2 - 何时从池中删除空闲连接的主要内容,如果未能解决你的问题,请参考以下文章
在 Wildfly-17 中的数据库故障转移期间回滚事务时,数据库连接不会从池中删除
[转]超时时间已到。超时时间已到,但是尚未从池中获取连接。出现这种情况可能是因为所有池连接均在使用,并且达到了最大池大小。
超时时间已到。超时时间已到,但是尚未从池中获取连接。出现这种情况可能是因为所有池连接均在使用,并且达到了最大池大小。
连接字符串中Min Pool Size的理解是错误,超时时间已到,但是尚未从池中获取连接。出现这种情况可能是因为所有池连接均在使用,并且达到了最大池大小。