我在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
非常感谢任何帮助。
答案 0 :(得分:7)
根据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池性能,超时和其他色调和螺栓的东西。当然,这需要一些深刻的专业知识。 (您可以在我最初提供的网站中找到详细信息)
答案 1 :(得分:4)
我在类似场景中所做的是保存请求连接的线程的线程栈,然后在另一个线程中打印出每分钟左右与每个打开的连接相关的线程栈。我想这是做这件事的蛮力方式。但我很快就解决了我的问题。
答案 2 :(得分:3)
确保始终关闭连接的一种相对简单的方法是将其放入servlet过滤器,将其放入ThreadLocal,通过所有代码使用ThreadLocal,然后在响应通过过滤器时关闭它。 (优化是将代理放入ThreadLocal,它只在第一个请求上获得连接。)
但你当前的问题是找到泄漏源,对吗?
首先,请确保关闭finally {}语句中的连接,因此异常不会阻止您执行此操作。
其次,目前还不清楚logAbandoned需要多长时间才能确定连接处于空闲状态。试着等一段时间,可能是15分钟左右。
第三,您可以使用代理JDBC驱动程序,例如http://code.google.com/p/log4jdbc/。它们会生成连接上所有活动的日志,因此您可以grep日志以查找不匹配的open()和close()。
祝你好运!