具有长时间运行请求的Spring Boot连接池 [英] spring boot connection pool with long running requests

查看:198
本文介绍了具有长时间运行请求的Spring Boot连接池的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

弹簧启动请求开始时,它会从池中获得连接.我的问题是-该连接是否仍与请求线程保持联系(即使它没有执行任何查询),并且仅在请求完成时才返回到池中?

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:

  1. 请求开始
  2. 执行查询(20毫秒)
  3. 呼叫外部http服务(1500毫秒)
  4. 请求完成

此请求线程获得的连接是否会在20ms或1520ms内被该线程占用(对其他请求不可用)?

Would the connection obtained by this request thread remain occupied with the thread (and not available to other requests) for 20ms or 1520ms?

PS:我正在将Spring Boot 2.0与HikariCP一起使用,而没有使用@Transactional.

PS: I'm using Spring Boot 2.0 with HikariCP and I'm not using @Transactional.

谢谢.

推荐答案

如果您的类路径中包含Spring MVC,除非您将spring.jpa.open-in-view配置为错误的.该拦截器将打开EntityManager的实例,并将其绑定到TransactionSynchronizationManager的整个请求期间.

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.

这意味着在第一次使用存储库查询时,它会从池中借用一个连接,并保留该连接,直到EntityManager被拦截器关闭时,直到请求结束.将连接返回到池是EntityManager的责任.因此,在这种情况下,您的示例将借用1520毫秒的连接.

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.

如果禁用spring.jpa.open-in-view选项,则在不使用任何显式事务的情况下,每次使用存储库查询时都会借用并返回一个连接.尽管这看起来更好,但是您必须记住,实体的托管实例将需要在每个持久性操作上重新进行系统附加,因此可能会造成高昂的成本.您还将失去EntityManager缓存的好处.为避免这种情况,请使用事务来读取/修改/保留您的实体,并避免重新附着.

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.

最后,请记住,如果禁用spring.jpa.open-in-view,由于请求期间没有EntityManager,因此您需要确保将惰性加载的关系加载到事务中,否则您会得到可怕的LazyInitializationException.

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.

这篇关于具有长时间运行请求的Spring Boot连接池的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆