连接池“泄漏”发展中。可能是由于 JUnit 测试设置所致?

发布于 2024-10-21 03:28:42 字数 328 浏览 1 评论 0原文

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

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

关于我们应该寻找什么还有其他想法吗?

我应该指出,我们使用 Jakarta Cactus 在 Glassfish 应用服务器上运行这些单元测试。

I am trying to track down a database connection pool "leak" in development and I am wondering if it is resulting from how the unit tests are set up. Something is grabbing database connections from the Glassfish pool and not closing them when done. Eventually the pool max connections are used up and the application is unable to get any new db connections.

Our JUnit tests get a connection from the pool in the setUp() method and then close that connection in the tearDown() method. Can we be sure that the tearDown() method will ALWAYS run? If an unhandled exception occurs, could the tearDown() method be bypassed?

Any other ideas on what we should look for?

I should note that we are using Jakarta Cactus to run these unit tests on the Glassfish application server.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

宣告ˉ结束 2024-10-28 03:28:42

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

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

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

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

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

范围的另一个示例是每个事务需要连接的情况。您可能需要使用 执行周围方法 模式来获取在范围开始之前连接并以确定的方式在结束时关闭它。

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

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

更新:

我刚刚通过向数据库连接池实现 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-->

 />

请参阅:Apache DBCP 配置

One suggestion to prevent and report the database connection leaks:

First find out the scope of each connection.

Example, for many web applications a connection is needed in the scope of a request.

With the scopes defined all you need to do is to close the connection in a deterministic way by doing it at the end of the scope life cycle.

One way to of asserting that a database connection is always closed in a web application is to create a servlet filter that will get the connection when a request comes in and close the connection when the response is sent. The connection can be passed from the filter to other objects by putting it in a ThreadLocal variable.

Another example of scope is when a connection is needed per transaction. You may want to use the Execute Around Method pattern to get the connection before the scope begin and close it at the end in a deterministic way.

If you implement any of these ideas you may even log which connections were not closed before you close it to help identify the leak.

Good luck, I hope this helps, please let me know otherwise.

Update:

I just solved a database connection leak in legacy code by adding debugging parameters to the database connection pool implementation apache DBCP.
Even if you don't want to use DBCP in production you could still set it up in test just to detect the exact line code that borrowed the unclosed connection.

In my environment I used tomcat with the JNDI datasource config like so :

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

 />

See : Apache DBCP configuration

つ低調成傷 2024-10-28 03:28:42

连接返回到池中

  1. 当您实际关闭连接时(最终阻塞!),
  2. 。发生完整的垃圾收集
  3. 。当java进程被终止时(停止服务器,单元周期结束)

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

A connection is returned to the pool when

  1. A connection is returned to the pool when you close it pragmatically (finally block!)
  2. A full garbage collection occurs
  3. When the java process is killed (stop server, end of unit cycle)

In short it is highly unlikely your pooling problems are caused by running unit tests.

烈酒灼喉 2024-10-28 03:28:42

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

但是:当tearDown内部抛出异常时,您可能会跳过tearDown的部分内容。

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

I have never seen that tearDown gets missed IF it is a proper tearDown (proper method signatur or annotation depending on the JUnit version)

But: You might skip parts of the tearDown when an exception gets thrown inside the tearDown.

I'd test your theory by running your TestSuite and watching the connection pool. Sounds fairly easy to me.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文