1

我正在尝试追踪开发中的数据库连接池“泄漏”,我想知道它是否是由单元测试的设置方式引起的。有些东西正在从 Glassfish 池中获取数据库连接,并且在完成后没有关闭它们。最终池最大连接数用完,应用程序无法获得任何新的数据库连接。

我们的 JUnit 测试在 setUp() 方法中从池中获取一个连接,然后在 tearDown() 方法中关闭该连接。我们能确定 tearDown() 方法总是会运行吗?如果发生未处理的异常,是否可以绕过 tearDown() 方法?

关于我们应该寻找什么的任何其他想法?

我应该注意到,我们正在使用 Jakarta Cactus 在 Glassfish 应用程序服务器上运行这些单元测试。

4

3 回答 3

1

连接返回到池时

  1. 当您实用地关闭它时,连接将返回到池中(最终阻塞!)
  2. 发生完整的垃圾回收
  3. 当java进程被杀死时(停止服务器,单元周期结束)

简而言之,您的池化问题极不可能是由运行单元测试引起的。

于 2011-03-10T14:50:08.353 回答
1

防止和报告数据库连接泄漏的一项建议:

首先找出每个连接的范围。

例如,对于许多 Web 应用程序,请求范围内需要连接。

定义好范围后,您需要做的就是在范围生命周期结束时以确定的方式关闭连接。

在 Web 应用程序中断言数据库连接始终关闭的一种方法是创建一个 servlet 过滤器,该过滤器将在请求进入时获取连接,并在发送响应时关闭连接。通过将连接放在 ThreadLocal 变量中,可以将连接从过滤器传递到其他对象。

范围的另一个示例是每个事务都需要连接时。您可能希望使用 Execute Around Method模式在范围开始之前获取连接,并在最后以确定性方式关闭它。

如果您实现了这些想法中的任何一个,您甚至可以在关闭连接之前记录哪些连接未关闭,以帮助识别泄漏。

祝你好运,我希望这会有所帮助,否则请告诉我。

更新:

我刚刚通过向数据库连接池实现 apache DBCP 添加调试参数解决了遗留代码中的数据库连接泄漏。即使您不想在生产中使用 DBCP,您仍然可以在测试中设置它,以检测借用未关闭连接的确切行代码。

在我的环境中,我使用了带有 JNDI 数据源配置的 tomcat,如下所示:

  <Resource auth="Container"
       name="jdbc/APP_NAME"
       username="user"
       password="password"
       url="jdbc:oracle:thin:@server.domain:1521:development"    
       type="javax.sql.DataSource"
       driverClassName="oracle.jdbc.driver.OracleDriver"

       maxIdle="10"
       maxWait="5000"
       maxActive="10"
       validationQuery="select 1 from dual"
       validationInterval="30000"
       testOnBorrow="true"
       testOnReturn="false"
       testWhileIdle="true"
       timeBetweenEvictionRunsMillis="5000"
       numTestsPerEvictionRun="3"
       minEvictableIdleTimeMillis="30000"


 <!-- These 3 settings saved me hours of headache -->

 logAbandoned="true" <!-- Will report the stacktrace of the faulty code --> 

 removeAbandoned="true" <!-- Will remedy the connection starvation while leaky code is not fixed-->

 removeAbandonedTimeout="60"<!-- Interval for fixing connection starvation while leaky code is not fixed-->

 />

请参阅:Apache DBCP 配置

于 2011-03-11T15:49:34.423 回答
0

如果它是正确的 tearDown (正确的方法签名或注释,取决于 JUnit 版本),我从未见过会错过 tearDown

但是:当在 tearDown 中抛出异常时,您可能会跳过一部分 tearDown。

我会通过运行您的 TestSuite 并观察连接池来测试您的理论。对我来说听起来很容易。

于 2011-03-10T14:50:54.700 回答