【问题标题】:Thread not releasing jdbc connection in spring bootThread not releasing jdbc connection in spring boot
【发布时间】:2022-12-01 20:23:37
【问题描述】:

We have a spring boot application whose starting point is an API. The API calls an interface say ITradeService which implements Callable. The ITradeService has a method service() which calls 7 methods in turn out of which the last three say method5() method6() and method7() are independent.

In the SIT,UAT environment for some reasons out of 4 nodes only one node is active and my project lead asked me to use 4 threads - 1 thread to execute the service method and other 3 threads to execute the above said 3 methods.

We have these three layers in our project

  • Controller(Rest API)
  • Service ITradeService
    TradeServiceImpl
    Type1TradeServiceImpl Type2TradeServiceImpl Type3TradeServiceImpl
  • DAO CommonDao Type1Dao Type2Dao Type3Dao

We use JdbcTemplate in each of our DAO classes.

In our application.yaml we have configured the hikari database connection pool as 2

When i tried to execute the threads using ThreadPoolTaskExecutor for 4 requests the process is working as expected but when i send the 5th request it is saying

CannotCreateTransactionException Could not open JDBC Connection for transaction

I understand that the 4 threads are holding the JDBC Connection. I should make the threads release the JDBC connection and send it back to the hikari connection pool or i should close the threads upon task completion

How should i do it in a spring specific way?

【问题讨论】:

  • 'project lead asked me to use 4 threads - 1 thread to execute the service method and other 3 threads to execute the above said 3 methods' - what is the rationale behind this request? It is generally a good idea to keep methods corresponding to a single unit of work on the same thread, as transactions do not span multiple threads. Please describe the actual use case a little better, then perhaps we might help
  • the 3 methods take a common input and sends messages to different queues .
  • Fair enough, but why does the enqueuing need to happen asynchronously? Couldn't those three methods just run serially?

标签: java spring spring-boot threadpool hikaricp


【解决方案1】:

It would be helpful to understandwhyyou feel you need to run those three methods in parallel.

In any case, you can solve/mitigate the issue by:

  • setting the appropriate connectionTimeout, and maximumPoolSize to make sure either the pool autoscales to meet the application demand, or the additional threads do not timeout while waiting for the connection to be released, and/or
  • making sure the time the connection is open during the execution of those three methods is as short as possible, e.g. the thread is not doing heavy calculations, file access etc. within a @Transactional method.

Regarding the second bullet point, if you absolutely need the operations to be atomic, perhaps you could use optimistic locking (pull out the information you need and finish the unit of work there, do the heavylifting on a detached copy of the data, initiate another unit of work, see if the data changed in the meantime, and if so, retry the whole process, otherwise just update the data with your copy).

【讨论】: