HikariCP 连接池 - '活动' - 如何调试?
Posted
技术标签:
【中文标题】HikariCP 连接池 - \'活动\' - 如何调试?【英文标题】:HikariCP connection pool - 'active' - how to debug?HikariCP 连接池 - '活动' - 如何调试? 【发布时间】:2018-11-09 10:22:30 【问题描述】:我正在使用 Spring-Boot/Hibernate 和 Postgres 作为数据库构建一个应用程序。我使用的是 Spring 2.0,所以 Hikari 是默认的连接池提供程序。
目前,我正在尝试使用 REST 端点对应用程序进行负载测试,该端点对数据库中的实体执行“如果存在更新并插入新的”。它是一个相当小的实体,具有“BIGSERIAL”主键,并且对任何其他字段没有任何限制。
默认连接池大小为 10,我没有真正调整任何其他参数 - 无论是 HikariCP 还是 Postgres。
我此刻卡住的地方是调试处于“活动”状态的连接以及它们正在做什么或它们当前卡住的原因。
当我运行“10 个同时用户”时,它基本上会转化为 2 或 3 倍的查询,因此,当我打开 HikariCP 调试日志时,它会挂在这样的地方 -
(total=10, active=10, idle=0, waiting=2)
和“活动”连接并没有真正释放连接,这是我想要找出的,因为查询相当简单,而且表本身只有 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 是正确的 - 连接泄漏不应该被池覆盖。
【问题讨论】:
如果在您的代码中创建了连接并且没有关闭它,您将无法找到它,除非您搜索您的代码或使用声纳工具来帮助您找到它 @user7294900 l 还怀疑连接未关闭是某个地方的问题。在这种情况下,连接管理是由休眠完成的,所以我并没有在连接管理代码中明确地做任何事情。我去看看 sonarlint,以前没听说过。 【参考方案1】:听起来您可能会在数据库中遇到真正的死锁。应该有一种方法可以查询 PostgreSQL 的当前活动查询和当前锁定状态。你必须谷歌它。
另外,我会尝试一个简单的线程转储来查看所有线程被阻塞的位置。可能是代码级同步死锁。
如果 所有 线程在getConnection()
上被阻塞,则表示泄漏。
如果驱动程序中的所有线程都已关闭,根据每个线程的堆栈跟踪,这是数据库死锁。
如果所有线程都在等待应用程序代码中的锁时被阻塞,那么您就会遇到同步死锁 - 可能是两个锁在代码的不同部分中具有相反的获取顺序。
HikariCP leakDetectionThreshold 可能很有用,但它只会显示获取连接的位置,而不是线程当前卡住的位置。不过,它可以提供线索。
【讨论】:
当连接耗尽并且所有连接都卡在getConnection()
- com.zaxxer.hikari.util.ConcurrentBag.borrow
时,我进行了线程转储。我阅读了您关于 Hibernate 未关闭此线程上的连接的评论 - github.com/brettwooldridge/HikariCP/issues/… 并且一旦我根据 - jira.spring.io/browse/SPR-14548 设置选项,它开始释放连接并且连接池不会耗尽。现在问题更多在于 API 响应级别,并且更容易推理。以上是关于HikariCP 连接池 - '活动' - 如何调试?的主要内容,如果未能解决你的问题,请参考以下文章
为啥HikariCP被号称为性能最好的Java数据库连接池,如何配置使用