У меня есть приложение, написанное на spring boot (версия 3.4.4), в которой выявилась медленная работа одного метода, который делает следующее:
public void method(Request request) {
databaseService.storeObject(request); // A
final var response = httpClient.post(request); // B
databaseService.storeObject(response); // C
}
Метод storeObject в точках A и C помечен как транзакционный, с помощью аннотации Transactional. В точке B задержка ответа около 100 мс.
При нагрузочном тестировании я заметил, что метод выполняется несоразмерно долго, т.е. среднее время ответа не 100 мс. Профилирование показало следующее:
- В точке А вызов метода может занимать несколько секунд
- Внутренности метода А выполняются около 1 мс.
- Запрос к внешней точке B всегда около 100 мс.
- В точке С вызов метода и внутренности его всегда укладываются в 1 мс
Судя по поведению, которое мы наблюдает, после выполнения точки А соединение не возвращается в пул соединений. Оно остается до окончания выполнения всего метода (который вызывается контроллером). Поэтому в точке С вызов всегда очень быстрый, ведь соединение уже есть. А вот другие запросы не могут войти в точку А, ведь свободных соединений нет, пока у кого-то другого не отработают точки В и С.
Я не могу понять, чем вызвано такое поведение. Под капотом неявно крутится hibernate - мы не используем его явно, только jpa репозитории. Вот зависимость дерева:
[INFO] +- org.springframework.boot:spring-boot-starter-data-jpa:jar:3.4.4:compile
[INFO] | +- org.springframework.boot:spring-boot-starter-jdbc:jar:3.4.4:compile
[INFO] | | +- com.zaxxer:HikariCP:jar:5.1.0:compile
[INFO] | | \- org.springframework:spring-jdbc:jar:6.2.5:compile
[INFO] | +- org.hibernate.orm:hibernate-core:jar:6.6.11.Final:compile
[INFO] | | +- jakarta.transaction:jakarta.transaction-api:jar:2.0.1:compile
Так же под капотом используется пул соединений hikari. Пробовал менять его на oracle UCP -не помогло особо, такое же поведение. Такое ощущение, что либо hibernate, либо jakarta transaction manager не дают правильно вернуть соединение после первой вставки в базу. Кто-нибудь сталкивался с этим, что с этим можно сделать?