简体   繁体   English

关闭连接后,数据连接池中的连接也不可用

[英]After closing connection also connection is unavailable from data connection pool

I am getting Unable to acquire connection when there are active thread who has already done DB work and waiting for some other API calls.当有活动线程已经完成数据库工作并等待其他一些 API 调用时,我无法获取连接。

This is flow and issue.这是流程和问题。

Request come and make DB select call.请求来拨打 DB select 电话。 After getting data from DB, we make some API call to get some other data.从 DB 获取数据后,我们调用 API 来获取其他数据。 If for some reason API call gets delay and at same time another thread come for flow then datasource timed out for getConnection for new request.如果由于某种原因 API 调用得到延迟,同时另一个线程来进行流处理,则数据源为新请求的 getConnection 超时。

Original implementation is on Spring JPA, then I tried with JDBCTemplate and even old school code as getConnection, prepareStatement and then close one by one but every time same issue.最初的实现是在 Spring JPA 上,然后我尝试使用 JDBCTemplate 甚至旧学校代码作为 getConnection,prepareStatement,然后一个一个地关闭,但每次都是同样的问题。 If thread is busy then getconnection doesn't work.如果线程很忙,则 getconnection 不起作用。

In my webapp, I am using jdbc pool with 70 connection in production but in local using only 2 connection to reproduce issue.在我的 webapp 中,我使用 jdbc 池在生产中具有 70 个连接,但在本地仅使用 2 个连接来重现问题。 So it work fine with 2 request at same time, but if I make 3rd request while 2 are still in process, it throws error.所以它可以同时处理 2 个请求,但是如果我在 2 个请求仍在处理中时发出第 3 个请求,则会引发错误。

I am unable to understand, if I make connection close or release then why still datasource is not giving the connection.我无法理解,如果我关闭或释放连接,那么为什么数据源仍然没有提供连接。

Below is sample code by keeping all control by my hand.下面是通过我的手保持所有控制的示例代码。

try{
LOGGER.debug("Trying to get connection");
con = datasource.getConnection();
LOGGER.debug("Trying to prepareStatement");
ps = con.prepareStatement("select * from table where itemnumber=?");
ps.setString(1, itemnumber);
LOGGER.debug("Trying to executeQuery");
ResultSet rs = ps.executeQuery();
while(rs.next()) {
    ufiles.add(rowMap.mapRow(rs, 0));
}


} catch (Exception e) {
        LOGGER.error("Error in execution ",e);
    } finally {

        try {
            if(ps!=null && !ps.isClosed()) {
                ps.close();
            }

            if(con!=null && !con.isClosed()) {
                con.close();
            }
        } catch (Exception e) {
            LOGGER.error("Error in closing connection ",e);
        }

    }

Connection pool XML连接池 XML

<dataSource id="STREAMAPP" jndiName="jdbc/APPDB" type="javax.sql.ConnectionPoolDataSource">
        <jdbcDriver libraryRef="ORACLEDRIVERLIB" />
        <connectionManager connectionTimeout="10s" minPoolSize="1" maxPoolSize="2" maxIdleTime="30s" agedTimeout="7200s" />
</dataSource>

Application logs应用程序日志

Trying to get connection试图建立连接
Trying to prepareStatement试图准备声明
Trying to executeQuery试图执行查询

Converted java object gets return and then we make API calls in another class and methods.转换后的 java object 得到返回,然后我们在另一个 ZA2F2ED4F8EBC2CBB614C21A29DZ40 方法和 AB 中调用 API。 Meanwhile if another request come then after waiting for 10 seconds getConnections gets timeout.同时,如果另一个请求出现,则在等待 10 秒后 getConnections 会超时。

Trying to get connection
Error in execution 
java.sql.SQLTransientConnectionException: Connection not available, Timed out waiting for 10000
    at com.ibm.ws.rsadapter.AdapterUtil.toSQLException(AdapterUtil.java:809)
    at com.ibm.ws.rsadapter.jdbc.WSJdbcDataSource.getConnection(WSJdbcDataSource.java:152)
    at com.ibm.ws.rsadapter.jdbc.WSJdbcDataSource.getConnection(WSJdbcDataSource.java:116)

After some more research all pointers leads to GC and connection pool implementation on server.经过更多研究,所有指针都指向服务器上的 GC 和连接池实现。 I didn't find any solution in config so at then end I split the DAO call and API call in two inbound request.我在配置中没有找到任何解决方案,所以最后我将 DAO 调用和 API 调用拆分为两个入站请求。

Consumer (UI) make 1st call to get data from DB.消费者 (UI) 进行第一次调用以从数据库中获取数据。 then after successful response UI make another API to call to invoke rest of the flow by passing response received from 1st(from DB).然后在成功响应 UI 后,让另一个 API 通过传递从第一个(来自 DB)收到的响应来调用流的 rest。

So as pool for actually releasing connection after thread get complete so after 1st request from UI, it immediately make connection available to next request.因此,作为线程完成后实际释放连接的池,因此在来自 UI 的第一个请求之后,它立即使连接可用于下一个请求。

By split that in two, now even I can make my app running with just one connection and having 20-30 request at same time because my DB call take just 100ms and connection timeout is 10 secs.通过将其一分为二,现在我什至可以让我的应用程序只运行一个连接并同时发出 20-30 个请求,因为我的数据库调用只需要 100 毫秒,连接超时是 10 秒。 So with just 1 one connection i can handle roughly 90-100 request.因此,只需 1 个连接,我就可以处理大约 90-100 个请求。 :) :)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM