Tomcat连接池:几种不释放连接的方法 [英] Tomcat Connection pool : few methods not releasing connection

查看:633
本文介绍了Tomcat连接池:几种不释放连接的方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用tomcat连接池。但我跟踪异常
org.apache.tomcat.dbcp.dbcp.SQLNestedException:无法获取连接,池错误超时等待空闲对象

I am using tomcat connection pooling. But I was following exception org.apache.tomcat.dbcp.dbcp.SQLNestedException: Cannot get a connection, pool error Timeout waiting for idle object

所以我在context.xml中输入以下行来查找泄漏:
removeAbandoned =truelogAbandoned =trueremoveAbandonedTimeout = 3

So I put in the following lines in context.xml to find the leak : removeAbandoned="true" logAbandoned="true" removeAbandonedTimeout="3"

然后我开始得到以下异常 org.apache.tomcat.dbcp.dbcp.AbandonedTrace $ AbandonedObjectException:通过以下代码创建的DBCP对象2015-01-17 22:12:18从未关闭:
所以我发现导致此泄漏的两个罪魁祸首方法。这两种方法有通用的连接方式,即调用unwrap来访问驱动程序特定的连接。

Then I started getting following exception org.apache.tomcat.dbcp.dbcp.AbandonedTrace$AbandonedObjectException: DBCP object created 2015-01-17 22:12:18 by the following code was never closed: So I found two culprit methods that were causing this leak. The two methods have common way of getting connection i.e. calling unwrap to get access to driver specific connection.

try (Connection conn = DataSourceConnectionPool.getConnection().unwrap(OracleConnection.class);
        OracleCallableStatement cstmt = (OracleCallableStatement) conn.prepareCall(MIGRATE_ACCOUNT)) {
        ...
        ....
)

重要的是要注意我是从JDK7使用try块,即自动资源管理,所以我不这样做需要最后一块。连接关闭由JDK自动处理。但为什么这个解开的连接没有关闭。当我尝试执行以下操作时:

Important think to notice is that I am using try block from JDK7 i.e. Automatic Resource Management, so i dont need the finally block. Connection closing is handled by JDK automatically. But why this unwrapped connection is not closing. And when I am trying to do following :

try (Connection poolConn = DataSourceConnectionPool.getConnection();
    Connection conn = poolConn.unwrap(OracleConnection.class);

我得到 java。 sql.SQLException:已经关闭。那么这个连接有多接近。我是否必须手动完成而不使用try块?不应该尝试使用块句柄来处理这个吗?

I am getting java.sql.SQLException: Already closed. So how close this connection. Do I have to do it manually without using try block? Shouldn't try block handle be able to handle this?

推荐答案

这是连接池的错误使用。你永远不应该在一个连接池上调用 close() unwrapped connection。

This is incorrect usage of a connection pool. You should never call close() on an unwrapped connection.

使用池化连接的正常流程是

The normal flow of using a pooled connection is


  1. 获取连接,池获取物理连接并将其包装在自己的包装器中

  2. 您使用连接

  3. 您在连接 close() $ c>。这实际上并没有关闭任何东西,游泳池' s wrapper拦截 close()调用,只返回池中的(仍处于活动状态)连接。

  1. Get the Connection, the pool gets a physical connection and returns it wrapped in its own wrapper
  2. You use the Connection
  3. You call close() on the Connection. This doesn't actually close anything, the pool's wrapper intercepts the close() call and simply returns the (still active) connection to the pool.

这是有效的,因为池有一个包装类,比如 PoolableConnection 实现Connection PoolableConnection 委托给底层连接以执行实际工作,但它实现(除其他外) close()以不同方式。这会破坏当前的 PoolableConnection 包装器,并将重要的连接返回到连接池。例如。

This works because the pool has a wrapper class, say PoolableConnection that implements Connection. PoolableConnection delegates to the underlying connection for carrying out actual work, but it implements (amongst other things) close() differently. This destroys the current PoolableConnection wrapper and returns the underying Connection to the connection pool. For example.

这样,您的程序逻辑可以从 DataSource 获得连接,使用连接然后 close(),就像正常的,未解化的连接

This way, your program logic can get a connection from a DataSource, use the Connection and then close(), just as it would a normal, unpooled, Connection.

正是这种透明性使连接池变得如此简单易用。

It's exactly this transparency that makes connection pools so easy to use.

现在,当你打电话给 unwrap PooledConnection 让你可以访问它的内部,真实,连接委托。

Now, when you call unwrap, the PooledConnection gives you access to it's internal, real, Connection delegate.

做的是打电话关闭() 代表

这有两个影响:


  1. 它不会在 PooledConnection 上调用 close(),所以连接没有返回池中。

  2. 它关闭了池下面的底层连接。这应该不是问题,因为池本身会处理掉线连接。

  1. it does not call close() on PooledConnection, so the the Connection does not get returned to the pool.
  2. it closes the underying connection from underneath the pool. This shouldn't be a problem, as the pool would deal with dropped connections itself.

所以你需要非常小心。 始终在您从游泳池中获得的连接上调用 close(),以便返回它到游泳池。 从不在底层连接上调用 close()

So you need to be very careful. Always call close() on the Connection you have gotten from the pool, to return it to the pool. Never call close() on the underlying connection.

所以你的代码应该是:

try (final Connection poolConn = DataSourceConnectionPool.getConnection()) {
    final Connection conn = poolConn.unwrap(OracleConnection.class);
    //do stuff with conn
    //do not close conn!!
}
//poolConn is returned to the pool

这篇关于Tomcat连接池:几种不释放连接的方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆