gpt4 book ai didi

java - 在 Tomcat 中启用 Context reload ="true"时,JDBC 连接池连接不足

转载 作者:IT老高 更新时间:2023-10-28 21:12:41 25 4
gpt4 key购买 nike

我正在 Eclipse Juno 中开发 Java EE Web 应用程序。我已将 Tomcat 配置为使用 JDBC 连接池 (org.apache.tomcat.jdbc.pool) 和 PostgreSQL 数据库。以下是我项目的 META-INF/context.xml 中的配置:

<?xml version="1.0" encoding="UTF-8"?>
<Context>
<!-- Configuration for the Tomcat JDBC Connection Pool -->
<Resource name="jdbc/someDB"
type="javax.sql.DataSource"
auth="Container"
factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"
driverClassName="org.postgresql.Driver"
url="jdbc:postgresql://localhost:5432/somedb"
username="postgres"
password="12345"
maxActive="100"
minIdle="10"
initialSize="10"
validationQuery="SELECT 1"
validationInterval="30000"
removeAbandoned="true"
removeAbandonedTimeout="60"
abandonWhenPercentageFull="50" />
</Context>

我的应用程序使用 Eclipse 部署到 Tomcat,并且在 Tomcat 的 context.xml 中,属性 reloadable 设置为“true”,以便在检测到更改时自动重新加载 Web 应用程序:

<Context reloadable="true">

我注意到,每次发生上述自动重新加载时,都会保留 10 多个与 PostgreSQL 数据库的连接(因为在 webapp 的 context.xml 中 initialSize="10")。所以在 10 次更改后会抛出 PSQLException:

org.postgresql.util.PSQLException: FATAL: sorry, too many clients already
...

如果我手动重启 Tomcat - 一切都很好,只保留了 10 个连接。

是否有人知道解决此问题的方法,因此可以将 reloadable 设置为“true”进行开发,并且每次重新加载上下文时不会导致池化更多连接?

不胜感激。

附: Apache Tomcat 版本 7.0.32

最佳答案

解决方案(tl;dr)

为了解决这个问题,添加一个属性 closeMethod(记录在 here)到 Resource 的值为“close” context.xml 文件中的元素。

这是我的/META-INF/context.xml 文件的正确内容:

<Context>
<!-- Configuration for the Tomcat JDBC Connection Pool -->
<Resource name="jdbc/someDB"
type="javax.sql.DataSource"
auth="Container"
factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"
driverClassName="org.postgresql.Driver"
url="jdbc:postgresql://localhost:5432/somedb"
username="postgres"
password="12345"
maxActive="100"
minIdle="10"
initialSize="10"
validationQuery="SELECT 1"
validationInterval="30000"
removeAbandoned="true"
removeAbandonedTimeout="60"
abandonWhenPercentageFull="50"
closeMethod="close" />
</Context>

注意属性closeMethod。我对其进行了测试,现在连接数严格按照 context.xml 文件中的定义进行保存!

注意
有一个时刻(与 JNDI 相关)需要处理。有关完整说明,请参阅更新 3。


长答案

好的,感谢 Apache Tomcat 提交者 Konstantin Kolinko,我找到了上述解决方案.我举报了this issue作为 ASF Bugzilla 上的一个 Apache Tomcat 错误, 结果证明这不是错误 (参见更新 1)。

=== 更新 1 (2012-12-03) 又名“新希望”===

好吧,它仍然是一个错误Mark Thomas ,Apache Tomcat 7 发布管理器,confirmed那(引用):

"This is a memory leak bug in jdbc-pool. PoolCleaner instances areretaining references to the ConnectionPool preventing it from beingGC'd.
...
This has been fixed in trunk and 7.0.x and will be included in7.0.34 onwards."

所以如果你的Tomcat版本较旧(低于7.0.34),请使用上述解决方案,否则, 从Apache Tomcat 7.0.34版本开始,应该不会出现我描述的问题。 (见更新 2)

=== UPDATE 2 (2014-01-13) 又名“问题反击” ===

这似乎是 my bug report 中最初描述的问题即使对于当前最新的 Apache Tomcat 版本 7.0.50 仍然存在,我还使用 Tomcat 7.0.47 复制了它(感谢 Miklos Krivan 指出)。虽然现在 Tomcat 有时会在重新加载后设法关闭额外的连接,有时重新加载后连接数会增加然后保持稳定,但最终这种行为仍然不可靠。

我仍然可以重现最初描述的问题(虽然也不是那么容易:它可能与连续重新加载的频率有关)。似乎这只是时间问题,即如果 Tomcat 在重新加载后有足够的时间,它会或多或少地管理连接池。正如马克·托马斯在他的 comment 中提到的那样(引用):“根据 closeMethod 的文档,该方法的存在仅仅是为了加速释放资源,否则这些资源会被 GC 释放。” (引用结束),看起来速度是决定性因素。

当使用 Konstantin Kolinko 提出的解决方案(使用 closeMethod="close")时,一切正常,并且保留的连接数严格按照 context.xml 文件中的定义保持。因此,使用 closeMethod="close" 似乎是(目前)避免在上下文重新加载后耗尽连接的唯一正确方法。

=== UPDATE 3 (2014-01-13) a.k.a. "Return of the Tomcat Release Manager"===

UPDATE 2 中描述的行为背后的谜团已解开。在我收到 reply 后,现在已经清除了更多详细信息来自 Mark Thomas(Tomcat 发布经理)。我希望这是最后一次更新。因此,正如更新 1 中提到的那样,该错误确实已修复。我将 Mark 回复中的重要部分作为引用发布在这里(强调我的):

The actual memory leak found while investigating this bug has beenfixed in 7.0.34 onwards as per comments #4 to #6.

The issue of the connections not being closed on reload is a result ofthe J2EE specification for JNDI resources and this part of the bugreport is therefore invalid. I am restoring the state of this bug tofixed to reflect that the memory leak that did exist has been fixed.

To expand on why the failure to immediately close connection afterreload is invalid, the J2EE specification provides no mechanism for thecontainer to tell the resource it is no longer required. Therefore allthe container can do is clear references to the resource and wait forgarbage collection (which will trigger the closure of the pool and theassociated connections). Garbage collection occurs at times determinedby the JVM so this is why it takes an indeterminate amount of time forconnections to be closed after a context reload as a garbagecollection may not occur for some time.

Tomcat has added the Tomcat specific JNDI attribute closeMethod whichcan be used to trigger the explicit close of a JNDI resource when acontext is stopped. If waiting for GC to clean up resources is notacceptable then simply use this parameter. Tomcat does not use thisby default as it may have unexpected and unwanted side-effects forsome JNDI resources.

If you'd like to see a standard mechanism provided for telling JNDIresources that they are no longer required then you need to lobby theJ2EE expert group.

结论

只需使用本文开头介绍的解决方案(但以防万一,请记住使用它理论上可能会出现的 JNDI 相关问题)。


替代解决方案

Michael Osipov建议使用他的CloseableResourceListener ,这可以防止在取消部署 Web 应用程序期间由未打开的资源导致的内存泄漏。所以你也可以试试看。


免责声明
UPDATES 的别名受到 Star Wars 的启发。电影系列。所有权利归其各自所有者所有。

关于java - 在 Tomcat 中启用 Context reload ="true"时,JDBC 连接池连接不足,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13595794/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com