Я создаю приложение, используя 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 Я также подозреваю, что соединение не закрывается, это проблема откуда-то. В этом случае управление подключением осуществляется с помощью спящего режима, поэтому я на самом деле ничего не делаю явно в коде для управления подключением. Я проверю сонарлинт, не слышал об этом раньше.





Похоже, вы можете попасть в настоящий тупик в базе данных. Должен быть способ запрашивать у PostgreSQL текущие активные запросы и текущие состояния блокировки. Вам придется погуглить.
Кроме того, я бы попробовал простой дамп потока, чтобы увидеть, где все потоки заблокированы. Это может быть тупик синхронизации на уровне кода.
getConnection(), это утечка.HikariCP leakDetectionThreshold может быть полезен, но он покажет только, где было получено соединение, а не где поток в данный момент застрял. Тем не менее, это может дать ключ к разгадке.
Я сделал дамп потока, когда соединения исчерпаны, и все соединения застревают на getConnection() в - com.zaxxer.hikari.util.ConcurrentBag.borrow. Я прочитал ваш комментарий о том, что Hibernate не закрывает соединение в этом потоке - github.com/brettwooldridge/HikariCP/issues/…, и как только я установил параметр в соответствии с - jira.spring.io/browse/SPR-14548, он начал освобождать соединения, и пул соединений не исчерпан. Теперь проблема больше связана с уровнем ответа API, и с ней легче договориться.
Если в вашем коде вы создаете соединение и не закрываете его, вы не сможете его найти, кроме как для поиска своего кода или использования инструментов, таких как sonarlint, чтобы помочь вам найти его.