我正在尝试在开发中追踪数据库连接池“泄漏”,我想知道它是否是由单元测试的设置方式产生的。有些东西正在从Glassfish池中获取数据库连接,并且在完成后不会关闭它们。最终,池最大连接用完,应用程序无法获得任何新的数据库连接。
我们的JUnit测试在setUp()方法中从池中获取连接,然后在tearDown()方法中关闭该连接。我们可以确定tearDown()方法总是会运行吗?如果发生未处理的异常,是否可以绕过tearDown()方法?
关于我们应该寻找什么的任何其他想法?
我应该注意到我们正在使用Jakarta Cactus在Glassfish应用服务器上运行这些单元测试。
答案 0 :(得分:1)
时会将连接返回到池中
简而言之,运行单元测试不太可能导致池化问题。
答案 1 :(得分:1)
防止和报告数据库连接泄漏的一个建议:
首先找出每个连接的范围。
示例,对于许多Web应用程序,请求范围内需要连接。
定义范围后,您需要做的就是在范围生命周期结束时以确定的方式关闭连接。
断言Web应用程序中始终关闭数据库连接的一种方法是创建一个servlet过滤器,该过滤器将在请求进入时获取连接,并在发送响应时关闭连接。通过将连接放入ThreadLocal变量,可以将连接从过滤器传递给其他对象。
范围的另一个示例是每个事务需要连接时。您可能希望使用Execute Around Method模式在范围开始之前获取连接,并以确定的方式在结束时关闭它。
如果您实施上述任何想法,您甚至可以在关闭之前记录哪些连接没有关闭,以帮助识别泄漏。
祝你好运,我希望这有帮助,请让我知道。更新
我刚刚通过向数据库连接池实现apache DBCP添加调试参数来解决遗留代码中的数据库连接泄漏问题。 即使您不想在生产中使用DBCP,您仍然可以在测试中将其设置为检测借用未闭合连接的确切行代码。
在我的环境中,我使用了tomcat和JNDI数据源配置,如下所示:
<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-->
/>
答案 2 :(得分:0)
我从来没有看到如果它是一个正确的tearDown(正确的方法signatur或注释取决于JUnit版本)会丢失tearDown
但是:当在tearDown中抛出异常时,你可能会跳过tearDown的部分内容。
我通过运行TestSuite并观察连接池来测试您的理论。听起来很容易。