我正在使用Spring-Boot / Hibernate和Postgres构建一个应用程序作为数据库。我使用的是Spring 2.0,因此Hikari是默认的连接池提供程序。
目前,我正在尝试使用REST端点对应用程序进行负载测试,该端点执行“update-if-exists并在数据库中为实体插入if new”。它是一个相当小的实体,具有“BIGSERIAL”主键,对其他任何领域都没有限制。
默认连接池大小为10,我没有真正调整任何其他参数 - 无论是HikariCP还是Postgres。
此时我陷入困境的关键是调试处于“活动”状态的连接以及它们正在做什么或者它们当前卡住的原因。
当我运行“10个并发用户”时,它基本上转化为许多查询的2到3倍,因此,当我打开HikariCP调试日志时,它会挂起类似这样的东西 -
(total=10, active=10, idle=0, waiting=2)
和'active'连接并没有真正释放连接,这是我想要找到的,因为查询非常简单,表本身只有4个字段(包括主键)。
HikariCP人员的最佳做法一般是增加连接池不是缩放的第一步。
如果我确实将连接池大小增加到20,那么事情就会开始为10个同时/并发用户工作,但是再次,它不是我认为的问题的根本原因/解决方案。
有没有什么方法可以记录Hibernate或Postgres消息,这些消息可能有助于了解这些“活动”连接正在等待什么以及为什么即使我将等待时间增加到很长时间之后连接也不会被释放?
如果是连接泄漏(如leak-detection-threshold
减少到较低值(例如30秒)时所报告的那样),那么如何判断Hibernate是否应对此连接泄漏负责?还有别的吗?
如果它是数据库级别的锁定/等待,我怎样才能获得它的根源?
更新
在@brettw的帮助下,当连接耗尽并且它指向连接泄漏的方向时,我进行了一个线程转储。 HikariCP上的线程发布板 - https://github.com/brettwooldridge/HikariCP/issues/1030#issuecomment-347632771 - 它指向Hibernate没有关闭连接然后指向我https://jira.spring.io/browse/SPR-14548,它讨论设置Hibernate的连接关闭模式,因为默认模式保持连接太长时间。设置spring.jpa.properties.hibernate.connection.handling_mode=DELAYED_ACQUISITION_AND_RELEASE_AFTER_TRANSACTION
后,连接池运行良好。
此外,这里提出的观点 - https://github.com/brettwooldridge/HikariCP/issues/612#issuecomment-209839908是正确的 - 连接泄漏不应该被池覆盖。
答案 0 :(得分:1)
听起来你可能会在数据库中遇到真正的死锁。应该有一种方法来查询PostgreSQL以获取当前活动查询和当前锁定状态。你必须谷歌。
另外,我会尝试一个简单的线程转储来查看所有线程被阻止的位置。它可能是代码级同步死锁。
getConnection()
阻止,那就是泄密。HikariCP leakDetectionThreshold可能很有用,但它只显示获取连接的位置,而不是线程当前卡住的位置。不过,它可以提供线索。