HikariCP 连接池 - 'active' - 如何调试?
HikariCP connection pool - 'active' - how to debug?
我正在使用 Spring-Boot/Hibernate 构建一个应用程序,并将 Postgres 作为数据库。我使用的是 Spring 2.0,因此 Hikari 是默认的连接池提供程序。
目前,我正在尝试使用对数据库中的实体执行 'update-if-exists and insert if new' 的 REST 端点对应用程序进行负载测试。它是一个相当小的实体,具有 'BIGSERIAL' 主键并且对任何其他字段没有限制。
默认连接池大小为 10,我还没有真正调整任何其他参数 - 无论是 HikariCP 还是 Postgres。
我现在卡住的地方是调试处于 'active' 状态的连接以及它们在做什么或它们当前卡住的原因。
当我 运行 '10 个并发用户'时,它基本上转化为查询数量的 2 或 3 倍,因此,当我打开 HikariCP 调试日志时,它挂在这样的地方 -
(total=10, active=10, idle=0, waiting=2)
和 'active' 连接并没有真正释放连接,这正是我试图找出的原因,因为查询相当简单并且 table 本身只有 4 个字段(包括主键)。
HikariCP 人员的最佳实践通常也是增加连接池并不是实现扩展的正确第一步。
如果我确实将连接池大小增加到 20,事情开始适用于 10 个 simultaneous/concurrent 用户,但话又说回来,我认为这不是问题的根源 cause/solution。
有什么方法可以记录 Hibernate 或 Postgres 消息,这些消息可能有助于了解这些 'active' 连接正在等待什么,以及为什么即使在我增加等待时间后连接仍未释放很长一段时间?
如果它是连接泄漏(如 leak-detection-threshold
减少到较低值(例如 30 秒)时所报告的那样),那么我如何判断 Hibernate 是否对此连接泄漏负责或如果是别的什么?
如果它是数据库级别的lock/wait,我怎样才能得到它的根?
更新
在@brettw 的帮助下,我在连接耗尽时进行了线程转储,它指向连接泄漏的方向。 HikariCP 上的线程问题板 - https://github.com/brettwooldridge/HikariCP/issues/1030#issuecomment-347632771 - which points to the Hibernate not closing connections which then pointed me to 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 是正确的 - 连接泄漏不应被池掩盖。
听起来您可能在数据库中遇到了真正的死锁。应该有一种方法可以查询 PostgreSQL 以获取当前活动查询和当前锁定状态。你必须 google 它。
另外,我会尝试一个简单的线程转储来查看所有线程被阻塞的位置。可能是代码级同步死锁。
- 如果所有 个线程在
getConnection()
上被阻塞,这是一个泄漏。
- 如果驱动程序中的所有线程都关闭,根据每个线程的堆栈跟踪,这是一个数据库死锁。
- 如果在您的应用程序代码中所有线程都被阻塞等待锁定,那么您就会遇到同步死锁——可能是代码的不同部分中的两个锁具有相反的获取顺序。
HikariCP leakDetectionThreshold 可能很有用,但它只会显示获取连接的位置,而不是当前线程卡住的位置。尽管如此,它还是可以提供线索。
我正在使用 Spring-Boot/Hibernate 构建一个应用程序,并将 Postgres 作为数据库。我使用的是 Spring 2.0,因此 Hikari 是默认的连接池提供程序。
目前,我正在尝试使用对数据库中的实体执行 'update-if-exists and insert if new' 的 REST 端点对应用程序进行负载测试。它是一个相当小的实体,具有 'BIGSERIAL' 主键并且对任何其他字段没有限制。
默认连接池大小为 10,我还没有真正调整任何其他参数 - 无论是 HikariCP 还是 Postgres。
我现在卡住的地方是调试处于 'active' 状态的连接以及它们在做什么或它们当前卡住的原因。
当我 运行 '10 个并发用户'时,它基本上转化为查询数量的 2 或 3 倍,因此,当我打开 HikariCP 调试日志时,它挂在这样的地方 -
(total=10, active=10, idle=0, waiting=2)
和 'active' 连接并没有真正释放连接,这正是我试图找出的原因,因为查询相当简单并且 table 本身只有 4 个字段(包括主键)。
HikariCP 人员的最佳实践通常也是增加连接池并不是实现扩展的正确第一步。
如果我确实将连接池大小增加到 20,事情开始适用于 10 个 simultaneous/concurrent 用户,但话又说回来,我认为这不是问题的根源 cause/solution。
有什么方法可以记录 Hibernate 或 Postgres 消息,这些消息可能有助于了解这些 'active' 连接正在等待什么,以及为什么即使在我增加等待时间后连接仍未释放很长一段时间?
如果它是连接泄漏(如 leak-detection-threshold
减少到较低值(例如 30 秒)时所报告的那样),那么我如何判断 Hibernate 是否对此连接泄漏负责或如果是别的什么?
如果它是数据库级别的lock/wait,我怎样才能得到它的根?
更新
在@brettw 的帮助下,我在连接耗尽时进行了线程转储,它指向连接泄漏的方向。 HikariCP 上的线程问题板 - https://github.com/brettwooldridge/HikariCP/issues/1030#issuecomment-347632771 - which points to the Hibernate not closing connections which then pointed me to 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 是正确的 - 连接泄漏不应被池掩盖。
听起来您可能在数据库中遇到了真正的死锁。应该有一种方法可以查询 PostgreSQL 以获取当前活动查询和当前锁定状态。你必须 google 它。
另外,我会尝试一个简单的线程转储来查看所有线程被阻塞的位置。可能是代码级同步死锁。
- 如果所有 个线程在
getConnection()
上被阻塞,这是一个泄漏。 - 如果驱动程序中的所有线程都关闭,根据每个线程的堆栈跟踪,这是一个数据库死锁。
- 如果在您的应用程序代码中所有线程都被阻塞等待锁定,那么您就会遇到同步死锁——可能是代码的不同部分中的两个锁具有相反的获取顺序。
HikariCP leakDetectionThreshold 可能很有用,但它只会显示获取连接的位置,而不是当前线程卡住的位置。尽管如此,它还是可以提供线索。