java 尝试在 tomcat 中识别废弃连接的来源

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5703955/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 12:24:09  来源:igfitidea点击:

Trying to identify source of abandoned connections in tomcat

javatomcatjdbc

提问by opike

I'm using dbcp connection pooling in tomcat (version 7) and I have a connection leak somewhere in my code. After a short amount of time, a request for a new connection returns the following exception:

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

"Cannot get a connection, pool error Timeout waiting for idle object"

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

I went back through my code and to me it looks like all connections are being closed properly (doesn't everyone say this...).

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

In order to debug this I added the following properties in context.xml:

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

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

So the resource tag now looks like this:

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

 <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"/>

I then restarted tomcat and started hitting web pages until the error message appeared (in the browser window). However I haven't yet been able to figure out where the "logAbandoned" property is writing its information. I'm looking in

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

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

but the only recently modified log file in there is

但那里唯一最近修改的日志文件是

localhost_access_log.2011-04-18.txt

Any assistance is much appreciated.

非常感谢任何帮助。

采纳答案by Nishan

What I did in a similar scenario was to save threadstacks of threads which requests connections, and then in another thread print out threadstacks pertaining to each open connection in every minute or so. I guess this is the brute force way of doing it. But I solved my issue pretty quickly.

我在类似场景中所做的是保存请求连接的线程的线程堆栈,然后在另一个线程中每隔一分钟左右打印出与每个打开的连接相关的线程堆栈。我想这是执行此操作的蛮力方式。但是我很快就解决了我的问题。

回答by DartCone

According to this siteyou must provide a factory to your resource definition from your context.xml. The configuration of the resource will be done by this factory instance so all the "additional" parameters are set this way. To be more specific you would have something like this in your context.xml (or server.xml - depends where you define your resource) :

根据此站点,您必须为您的 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" />  

Notice the factory="org.apache.tomcat.jdbc.pool.DataSourceFactory"which is essential for our purpose. Without it the removeAbandoned="true"has no effect.

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

The stacks of each connection that is abandoned is stored in the catalina.log ($tomcat_dir/logs). From there it will give pretty accurate details for debugging connections.

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

Other than "abandoned" parameters you can configure a lot of stuff with relation to tomcat jdbc pool performance , timeouts and other tints and bolts. Of course this requires some deep know-how. (You can find details in the site I initially provided)

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

回答by Vladimir Dyuzhev

One relatively easy way to make sure you always close a connection is to get it in the servlet filter, place it into ThreadLocal, use that ThreadLocal through all your code, and then close it when response goes back through the filter. (An optimization would be to place a proxy into the ThreadLocal which gets connection on the first request only).

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

But your immediate problem is to find the leak source, right?

但是您当前的问题是找到泄漏源,对吗?

First, make sure you close the connections in finally{} statement, so an exception wouldn't prevent you from doing it.

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

Second, it is unclear how long it takes for logAbandoned to figure out the connection is idle. Try to wait for some time, may be 15 minutes or so.

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

Third, you may use proxy JDBC drivers such as http://code.google.com/p/log4jdbc/. They generate a log of all activities over connections, so you may grep the log to find mismatching open() and close().

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

Good luck!

祝你好运!