Я использую стандартную реализацию HikariCP с последним приложением SpringBoot. Сценарий такой. В мой API делается вызов, который берет что-то из БД и после этого вызывает другой микросервис. По умолчанию пул HikariCP равен 10. Ответ на вызов внутренней микрослужбы может занять до 20 минут. Сценарий:
External Client -> MyApi -> SomeMicroService <- reponse time 20 minutes.
Если у меня есть 11 запросов параллельно, у меня проблема, потому что я получаю:
HikariPool-1 - Connection is not available, request timed out after 30000ms
Почему? Потому что соединение возвращается в пул после закрытия сеанса.
Есть ли способ закрыть соединение после вызова БД? Если в одном сеансе у нас есть 10 запросов JPA, используется одно и то же соединение, но если у вас есть 30 параллельных вызовов, 10 будет нормально, а 20 завершатся ошибкой.
Я знаю, что могу увеличить пул с 10 до 100, но есть ли другое решение. @Transaction не работает. Соединение остается открытым до тех пор, пока запрос не будет разрешен тем или иным способом.
Итак, мой вопрос: как разорвать соединение после того, как запрос / ответ БД сделан, и создать еще одно, когда это необходимо.
Я использую SpringBoot, SprinJPA, спящий режим с конфигурациями по умолчанию.
Заранее спасибо.
@robert - вторая MS находится на другом компьютере в другой сети.
Что ж, способ есть. Не заключайте внутренний вызов микросервиса в транзакцию вместе с вызовом доступа к локальной БД. Соединения обычно возвращаются в пул, когда транзакции завершаются и соединение простаивает.
Да, правда @crizzis. Мне нужно увеличить тайм-аут до 20 минут и 40 секунд и простоя до 30 секунд (по умолчанию 10 минут), и он должен работать, однако запрос 11 будет разрешен через 40 минут и 40 секунд, если произойдет худший сценарий.
Если вы имеете в виду idleTimeout
, то я считаю, что это свойство представляет собой время после простоя соединения уничтожен, которое не возвращается обратно в пул (как способ уменьшение размера пула, когда вашему приложению требуется очень мало активных соединений). У вас действительно должно быть всего три вызова метода transactionalOne(); fetchDataFromExternalApi(); transactionalTwo()
. Убедитесь, что TransactionSynchronizationManager.isActualTransactionActive()
возвращает false
из «среднего» метода.
@crizzis - проблема не связана с транзакциями. Проблема в том, что для каждого запроса система бронирует соединение из пула соединений, и это соединение разрывается после завершения сеанса. Я пробовал ваш подход и не работает. Однако использование Executor с Callable работает нормально. В этом Callable я делаю свой запрос JPA, и соединение блокируется, пока этот поток выполняет запрос JPA и немедленно освобождается.
Насколько я понимаю, обработка соединения - это абсолютно относится к транзакционным. Таким образом, если завершенная транзакция не приводит к возврату подключения к пулу, и вы не используете @PersistenceContext(type = EXTENDED)
, это звучит как утечка ресурсов. Возможно, я ошибаюсь
Я предполагаю, что
SomeMicroService
- это тот же экземпляр, в таком случае, возможно, здесь поможет @EnableTask.