问题
When a spring boot request starts, it obtains a connection from the pool. My question is - is this connection remains tied to the request thread (even if it is not executing any query) and only returned to the pool when request completes?
For example, if I'm doing something like:
- Request starts
- Execute a query (20ms)
- Call external http service (1500ms)
- Request completes
Would the connection obtained by this request thread remain occupied with the thread (and not available to other requests) for 20ms or 1520ms?
PS: I'm using Spring Boot 2.0 with HikariCP and I'm not using @Transactional.
Thanks.
回答1:
If you have Spring MVC on your classpath, Spring will configure an instance of OpenEntityManagerInViewInterceptor
automatically (in org.springframework.boot.autoconfigure.orm.jpa.JpaBaseConfiguration.JpaWebConfiguration
), unless you configure spring.jpa.open-in-view
to false. This interceptor will open an instance of EntityManager
and bind it to the TransactionSynchronizationManager
for the whole duration of the request.
What that means is that at the first use of a repository query, it will borrow a connection from the pool and keep it until the end of the request when the EntityManager
is closed by the interceptor. It's the EntityManager
's responsibility to return the connection to the pool. So, in that case, the connection will be borrowed for 1520ms in your example.
If you disable the spring.jpa.open-in-view
option, a connection will be borrowed and returned at each use of a repository query given you don't use any explicit transaction. While this may look better, you have to keep in mind that managed instances of your entities will need to be reattached systematically on each persist operation so it may be costly. You will also loose the benefits of the EntityManager
caching. To avoid this, use transactions to read/modify/persist your entities and avoid reattaching.
Finally, keep in mind that if you disable spring.jpa.open-in-view
, since you don't have an EntityManager
around for the duration of the request, you will need to make sure your lazy loaded relations are loaded inside a transaction otherwise you'll get the dreaded LazyInitializationException
.
回答2:
Basically it depends,
If you close conection it will be release back to pool and will be ready soon according to configuration (below) so it will be ~20ms (+ time to get back to pool)
If you don't close the connection it will wait until the configuration allow it, if it allow indefinite time, theoretically it can be causing a leak in your application and not return to pool until apllication is shutdown.
See answer about Hikari handling returning connections to pool:
The Hikari housekeeper runs every 30s, which closes any connections that are not in use and are older than maxLifetime. If there are more than minimumIdle number of connections the housekeeper will close connections that have been idle for longer than idleTimeout.
See more about max life time of connection:
by default Oracle does not enforce a max lifetime for connections (neither on JDBC driver side (1), nor on server side(2)). So in this respect, the "infrastructure-imposed connection time limit" is +infinity
来源:https://stackoverflow.com/questions/52924419/spring-boot-connection-pool-with-long-running-requests