试图识别tomcat中废弃连接的来源

Posted

技术标签:

【中文标题】试图识别tomcat中废弃连接的来源【英文标题】:Trying to identify source of abandoned connections in tomcat 【发布时间】:2011-08-07 22:02:58 【问题描述】:

我在 tomcat(第 7 版)中使用 dbcp 连接池,但我的代码中某处存在连接泄漏。短时间后,新连接请求返回以下异常:

“无法获取连接,池错误超时等待空闲对象”

我回顾了我的代码,在我看来,所有连接都已正确关闭(不是每个人都这么说...)。

为了调试它,我在 context.xml 中添加了以下属性:

logAbandoned="true" removeAbandoned="true" removeAbandonedTimeout="300"

所以资源标签现在看起来像这样:

 <Resource name="jdbc/findata" auth="Container" type="javax.sql.DataSource"
               maxActive="20" maxIdle="5" maxWait="10000"
               username="root" password="xxxxxx" driverClassName="com.mysql.jdbc.Driver"
               logAbandoned="true" removeAbandoned="true" removeAbandonedTimeout="300"
               url="jdbc:mysql://localhost:3306/findata"/>

然后我重新启动了 tomcat 并开始访问网页,直到出现错误消息(在浏览器窗口中)。但是我还不能弄清楚“logAbandoned”属性在哪里写入它的信息。我在看

/usr/share/apache-tomcat-7.0.11/logs

但其中唯一最近修改的日志文件是

localhost_access_log.2011-04-18.txt

非常感谢任何帮助。

【问题讨论】:

我从来没有最终弄清楚如何让废弃的连接显示在日志中,但我又重新查看了代码,这次我成功地找出了泄漏。谁需要调试器或日志——对吗? ;) 【参考方案1】:

根据this site,您必须从您的 context.xml 中为您的资源定义提供一个工厂。资源的配置将由该工厂实例完成,因此所有“附加”参数都以这种方式设置。更具体地说,您的 context.xml (或 server.xml - 取决于您定义资源的位置)中会有类似的内容:

<Resource name="jdbc/db" auth="Container" type="javax.sql.DataSource"
 factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"
 driverClassName="org.postgresql.Driver" url="jdbc:postgresql://127.0.0.1/db"
 username="hibernate" password="hibernate" maxActive="20" maxIdle="10"
 maxWait="1000" removeAbandoned="true" removeAbandonedTimeout="20"
 logAbandoned="true" />  

注意factory="org.apache.tomcat.jdbc.pool.DataSourceFactory",这对我们的目的至关重要。没有它,removeAbandoned="true" 无效。

每个被放弃的连接的堆栈都存储在 catalina.log ($tomcat_dir/logs) 中。从那里它将为调试连接提供非常准确的详细信息。

除了“废弃”参数之外,您还可以配置很多与 tomcat jdbc 池性能、超时和其他颜色和螺栓相关的东西。当然,这需要一些深厚的专业知识。 (您可以在我最初提供的网站中找到详细信息)

【讨论】:

您在哪里找到工厂对于 removeAbandoned 至关重要的信息?我的本地配置中没有工厂。但是,废弃的连接正在关闭。 这是在tomcat 7文档tomcat.apache.org/tomcat-7.0-doc/jdbc-pool.html987654322@中要求的 Tomcat JDBC 池和 Apache DBCP 池是两个不同的东西。如果你不指定...tomcat.jdbc.pool...作为工厂,Tomcat将默认使用DBCP,OP就是这种情况(“我在tomcat中使用dbcp连接池[.. .]").【参考方案2】:

我在类似情况下所做的是保存请求连接的线程的线程堆栈,然后在另一个线程中每分钟左右打印出与每个打开的连接相关的线程堆栈。我想这是蛮力的做法。但我很快就解决了我的问题。

【讨论】:

好一个。并在 close() 上从地图中删除堆栈,对吗?简单高效。【参考方案3】:

确保始终关闭连接的一种相对简单的方法是将其放入 servlet 过滤器,将其放入 ThreadLocal,在所有代码中使用该 ThreadLocal,然后在响应通过过滤器返回时关闭它。 (优化是在 ThreadLocal 中放置一个代理,它只在第一个请求时获得连接)。

但是你的直接问题是找到泄漏源,对吧?

首先,确保您在 finally 语句中关闭连接,这样异常不会阻止您这样做。

其次,尚不清楚 logAbandoned 需要多长时间才能确定连接处于空闲状态。尝试等待一段时间,可能是 15 分钟左右。

第三,您可以使用代理 JDBC 驱动程序,例如 http://code.google.com/p/log4jdbc/ 。它们会通过连接生成所有活动的日志,因此您可以通过 grep 日志查找不匹配的 open() 和 close()。

祝你好运!

【讨论】:

以上是关于试图识别tomcat中废弃连接的来源的主要内容,如果未能解决你的问题,请参考以下文章

如何废弃cricinfo中的所有测试匹配详细信息

@RequestBody 接收数组List 参数@Deprecated 标记废弃方法

php7已经放弃mysql_connect() 支持,php5.5可以,是废弃函数

最强 JDK15 安装与讲解,有点想升级,终于要废弃偏向锁了!

FreeBSD 为啥要废弃 GCC 改用 Clang/LLVM

Day724. 如何改进代码废弃 -Java8后最重要新特性