spring 具有长 运行 请求的启动连接池
spring boot connection pool with long running requests
当 spring 启动请求启动时,它会从池中获取连接。我的问题是 - 这个连接是否仍然与请求线程相关联(即使它没有执行任何查询)并且只在请求完成时才返回到池中?
例如,如果我正在做类似的事情:
- 请求开始
- 执行查询(20 毫秒)
- 调用外部 http 服务(1500 毫秒)
- 请求完成
此请求线程获得的连接是否会被线程占用(并且对其他请求不可用)20 毫秒或 1520 毫秒?
PS:我正在使用 Spring Boot 2.0 和 HikariCP,我没有使用 @Transactional。
谢谢。
基本看情况,
如果您关闭连接,它将被释放回池中,并根据配置(如下)很快准备就绪,因此大约需要 20 毫秒(+ 返回池的时间)
如果您不关闭连接,它将一直等到配置允许它,如果它允许不确定的时间,理论上它可能会导致您的应用程序泄漏,而不是 return 池直到应用程序是关机。
请参阅 answer 关于 Hikari 处理 returning 到池的连接:
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.
查看更多关于 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
如果您的类路径上有 Spring MVC,Spring 将自动配置 OpenEntityManagerInViewInterceptor
的实例(在 org.springframework.boot.autoconfigure.orm.jpa.JpaBaseConfiguration.JpaWebConfiguration
中),除非您配置 spring.jpa.open-in-view
为假。此拦截器将打开 EntityManager
的一个实例,并在整个请求期间将其绑定到 TransactionSynchronizationManager
。
这意味着在第一次使用存储库查询时,它将从池中借用一个连接并将其保留到请求结束时 EntityManager
被拦截器关闭。 EntityManager
负责 return 连接到池。因此,在这种情况下,您的示例中的连接将被借用 1520 毫秒。
如果您禁用 spring.jpa.open-in-view
选项,假设您不使用任何显式事务,每次使用存储库查询时都会借用和 returned 连接。虽然这可能看起来更好,但您必须记住,您的实体的托管实例将需要在每个持久化操作上系统地重新附加,因此它可能代价高昂。您还将失去 EntityManager
缓存的好处。为避免这种情况,请使用事务处理 read/modify/persist 您的实体并避免重新附加。
最后,请记住,如果您禁用 spring.jpa.open-in-view
,因为在请求期间您没有 EntityManager
,您将需要确保您的惰性加载关系被加载到事务中,否则你会得到可怕的 LazyInitializationException
.
当 spring 启动请求启动时,它会从池中获取连接。我的问题是 - 这个连接是否仍然与请求线程相关联(即使它没有执行任何查询)并且只在请求完成时才返回到池中?
例如,如果我正在做类似的事情:
- 请求开始
- 执行查询(20 毫秒)
- 调用外部 http 服务(1500 毫秒)
- 请求完成
此请求线程获得的连接是否会被线程占用(并且对其他请求不可用)20 毫秒或 1520 毫秒?
PS:我正在使用 Spring Boot 2.0 和 HikariCP,我没有使用 @Transactional。
谢谢。
基本看情况,
如果您关闭连接,它将被释放回池中,并根据配置(如下)很快准备就绪,因此大约需要 20 毫秒(+ 返回池的时间)
如果您不关闭连接,它将一直等到配置允许它,如果它允许不确定的时间,理论上它可能会导致您的应用程序泄漏,而不是 return 池直到应用程序是关机。
请参阅 answer 关于 Hikari 处理 returning 到池的连接:
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.
查看更多关于 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
如果您的类路径上有 Spring MVC,Spring 将自动配置 OpenEntityManagerInViewInterceptor
的实例(在 org.springframework.boot.autoconfigure.orm.jpa.JpaBaseConfiguration.JpaWebConfiguration
中),除非您配置 spring.jpa.open-in-view
为假。此拦截器将打开 EntityManager
的一个实例,并在整个请求期间将其绑定到 TransactionSynchronizationManager
。
这意味着在第一次使用存储库查询时,它将从池中借用一个连接并将其保留到请求结束时 EntityManager
被拦截器关闭。 EntityManager
负责 return 连接到池。因此,在这种情况下,您的示例中的连接将被借用 1520 毫秒。
如果您禁用 spring.jpa.open-in-view
选项,假设您不使用任何显式事务,每次使用存储库查询时都会借用和 returned 连接。虽然这可能看起来更好,但您必须记住,您的实体的托管实例将需要在每个持久化操作上系统地重新附加,因此它可能代价高昂。您还将失去 EntityManager
缓存的好处。为避免这种情况,请使用事务处理 read/modify/persist 您的实体并避免重新附加。
最后,请记住,如果您禁用 spring.jpa.open-in-view
,因为在请求期间您没有 EntityManager
,您将需要确保您的惰性加载关系被加载到事务中,否则你会得到可怕的 LazyInitializationException
.