草庐IT

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

coder 2023-05-16 原文

我正在 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 are retaining references to the ConnectionPool preventing it from being GC'd.
...
This has been fixed in trunk and 7.0.x and will be included in 7.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 been fixed in 7.0.34 onwards as per comments #4 to #6.

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

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

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

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

结论

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


替代解决方案

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


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

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

有关java - 在 Tomcat 中启用 Context reload ="true"时,JDBC 连接池连接不足的更多相关文章

  1. ruby-on-rails - rails : "missing partial" when calling 'render' in RSpec test - 2

    我正在尝试测试是否存在表单。我是Rails新手。我的new.html.erb_spec.rb文件的内容是:require'spec_helper'describe"messages/new.html.erb"doit"shouldrendertheform"dorender'/messages/new.html.erb'reponse.shouldhave_form_putting_to(@message)with_submit_buttonendendView本身,new.html.erb,有代码:当我运行rspec时,它失败了:1)messages/new.html.erbshou

  2. ruby-on-rails - 由于 "wkhtmltopdf",PDFKIT 显然无法正常工作 - 2

    我在从html页面生成PDF时遇到问题。我正在使用PDFkit。在安装它的过程中,我注意到我需要wkhtmltopdf。所以我也安装了它。我做了PDFkit的文档所说的一切......现在我在尝试加载PDF时遇到了这个错误。这里是错误:commandfailed:"/usr/local/bin/wkhtmltopdf""--margin-right""0.75in""--page-size""Letter""--margin-top""0.75in""--margin-bottom""0.75in""--encoding""UTF-8""--margin-left""0.75in""-

  3. ruby - 检查 "command"的输出应该包含 NilClass 的意外崩溃 - 2

    为了将Cucumber用于命令行脚本,我按照提供的说明安装了arubagem。它在我的Gemfile中,我可以验证是否安装了正确的版本并且我已经包含了require'aruba/cucumber'在'features/env.rb'中为了确保它能正常工作,我写了以下场景:@announceScenario:Testingcucumber/arubaGivenablankslateThentheoutputfrom"ls-la"shouldcontain"drw"假设事情应该失败。它确实失败了,但失败的原因是错误的:@announceScenario:Testingcucumber/ar

  4. ruby - 续集在添加关联时访问many_to_many连接表 - 2

    我正在使用Sequel构建一个愿望list系统。我有一个wishlists和itemstable和一个items_wishlists连接表(该名称是续集选择的名称)。items_wishlists表还有一个用于facebookid的额外列(因此我可以存储opengraph操作),这是一个NOTNULL列。我还有Wishlist和Item具有续集many_to_many关联的模型已建立。Wishlist类也有:selectmany_to_many关联的选项设置为select:[:items.*,:items_wishlists__facebook_action_id].有没有一种方法可以

  5. java - 等价于 Java 中的 Ruby Hash - 2

    我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/

  6. ruby-on-rails - 迷你测试错误 : "NameError: uninitialized constant" - 2

    我遵循MichaelHartl的“RubyonRails教程:学习Web开发”,并创建了检查用户名和电子邮件长度有效性的测试(名称最多50个字符,电子邮件最多255个字符)。test/helpers/application_helper_test.rb的内容是:require'test_helper'classApplicationHelperTest在运行bundleexecraketest时,所有测试都通过了,但我看到以下消息在最后被标记为错误:ERROR["test_full_title_helper",ApplicationHelperTest,1.820016791]test

  7. ruby - 无法在 60 秒内获得稳定的 Firefox 连接 (127.0.0.1 :7055) - 2

    我使用的是Firefox版本36.0.1和Selenium-Webdrivergem版本2.45.0。我能够创建Firefox实例,但无法使用脚本继续进行进一步的操作无法在60秒内获得稳定的Firefox连接(127.0.0.1:7055)错误。有人能帮帮我吗? 最佳答案 我遇到了同样的问题。降级到firefoxv33后一切正常。您可以找到旧版本here 关于ruby-无法在60秒内获得稳定的Firefox连接(127.0.0.1:7055),我们在StackOverflow上找到一个类

  8. ruby-on-rails - 相关表上的范围为 "WHERE ... LIKE" - 2

    我正在尝试从Postgresql表(table1)中获取数据,该表由另一个相关表(property)的字段(table2)过滤。在纯SQL中,我会这样编写查询:SELECT*FROMtable1JOINtable2USING(table2_id)WHEREtable2.propertyLIKE'query%'这工作正常:scope:my_scope,->(query){includes(:table2).where("table2.property":query)}但我真正需要的是使用LIKE运算符进行过滤,而不是严格相等。然而,这是行不通的:scope:my_scope,->(que

  9. 使用 ACL 调用 upload_file 时出现 Ruby S3 "Access Denied"错误 - 2

    我正在尝试编写一个将文件上传到AWS并公开该文件的Ruby脚本。我做了以下事情:s3=Aws::S3::Resource.new(credentials:Aws::Credentials.new(KEY,SECRET),region:'us-west-2')obj=s3.bucket('stg-db').object('key')obj.upload_file(filename)这似乎工作正常,除了该文件不是公开可用的,而且我无法获得它的公共(public)URL。但是当我登录到S3时,我可以正常查看我的文件。为了使其公开可用,我将最后一行更改为obj.upload_file(file

  10. ruby - 安装 Ruby 时遇到问题(无法下载资源 "readline--patch") - 2

    当我尝试安装Ruby时遇到此错误。我试过查看this和this但无济于事➜~brewinstallrubyWarning:YouareusingOSX10.12.Wedonotprovidesupportforthispre-releaseversion.Youmayencounterbuildfailuresorotherbreakages.Pleasecreatepull-requestsinsteadoffilingissues.==>Installingdependenciesforruby:readline,libyaml,makedepend==>Installingrub

随机推荐