一尘不染

Tomcat连接池:几种不释放连接的方法

tomcat

我正在使用tomcat连接池。但是我在跟踪异常 org.apache.tomcat.dbcp.dbcp.SQLNestedException: Cannot get a connection, pool error Timeout waiting for idle object

所以我在context.xml中放入以下行以查找泄漏: removeAbandoned="true" logAbandoned="true" removeAbandonedTimeout="3"

然后,我开始跟踪异常,org.apache.tomcat.dbcp.dbcp.AbandonedTrace$AbandonedObjectException: DBCP object created 2015-01-17 22:12:18 by the following code was never closed: 因此发现了导致此泄漏的两种罪魁祸首方法。两种方法都有获得连接的通用方法,即调用unwrap获得对驱动程序特定连接的访问​​权限。

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

需要注意的重要思想是,我正在使用来自JDK7的try块,即“自动资源管理”,因此我不需要finally块。连接关闭由JDK自动处理。但是为什么这个展开的连接没有关闭。当我尝试执行以下操作时:

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

我正在获得java.sql.SQLException: Already closed.如此紧密的联系。我是否必须手动执行而不使用try块?不应该尝试阻止句柄来处理吗?


阅读 322

收藏
2020-06-16

共1个答案

一尘不染

这是对连接池的不正确使用。您永远不应调用close()未包装的连接。

使用池连接的正常流程是

  1. 获取Connection,池获得物理连接并返回包装在其自己的包装器中的包装
  2. 您使用 Connection
  3. 你叫close()Connection。这实际上并没有 关闭 任何内容,池的包装程序拦截了该close()调用,并仅将(仍处于活动状态的)连接返回到池。

之所以有效,是因为该池具有包装器类,PoolableConnection即that implements ConnectionPoolableConnection委托底层连接来执行实际工作,但是(除其他事项外)实现方式close()有所不同。这将破坏当前的PoolableConnection包装,并将底层组件返回Connection到连接池。例如。

这样,您的程序逻辑就可以从中获取连接,然后DataSource使用Connectionclose(),就像正常的非池化一样Connection

正是这种透明性使连接池易于使用。

现在,当您调用时unwrapPooledConnection您就可以访问它的内部真实Connection委托。

什么 ,你 要做的就是调用close() 的委托

这有两个效果:

  1. 它不叫close()PooledConnection,所以在Connection没有得到返回到池中。
  2. 它关闭了池底的底层连接。这不应该成为问题,因为池本身将处理掉线的连接。

因此,您需要非常小心。 总是close()Connection你已经从池中得到,将其返回到池中。 永远不要
调用close()基础连接。

因此,您的代码应为:

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
2020-06-16