H2 - пул соединений Tomcat jdbc не восстанавливает соединения после достижения максимального предела - PullRequest
0 голосов
/ 04 мая 2018

Постановка задачи

Мы уже давно используем H2 во встроенном режиме. Над ним настроен пул соединений. Ниже приведена текущая конфигурация пула:

h2.datasource.min-idle=10
h2.datasource.initial-size=10
h2.datasource.max-active=200
h2.datasource.max-age=600000
h2.datasource.max-wait=3000
h2.datasource.min-evictable-idle-time-millis=60000
h2.datasource.remove-abandoned=true
h2.datasource.remove-abandoned-timeout=60
h2.datasource.log-abandoned=true
h2.datasource.abandonWhenPercentageFull=100

Конфигурация H2:

spring.h2.console.enabled=true
spring.h2.console.path=/h2
h2.datasource.url=jdbc:h2:file:~/h2/cartdb
h2.server.properties=webAllowOthers
spring.h2.console.settings.web-allow-others=true
h2.datasource.driver-class-name=org.h2.Driver

* пропуск имени пользователя и пароля.

Мы убедились, что указанная выше конфигурация вступает в силу, зарегистрировав свойства пула.

Проблема с этой настройкой заключается в том, что мы наблюдаем регулярное (хотя и прерывистое) истощение пула соединений, и как только пул достигает максимального предела, он начинает выдавать следующее исключение для некоторых запросов.

SqlExceptionHelper.logExceptions (SqlExceptionHelper.java:129) - [http-apr-8080-exec-38] Время ожидания: пул пуст. Невозможно получить соединение в течение 3 секунд, недоступно [размер: 200; занят: 200; холостой ход: 0; lastwait: 3000]

.

И после этого он не может выйти из этого состояния даже через много часов, пока мы не перезапустим веб-сервер (в данном случае tomcat).

Зависимость драйвера H2:

<dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
    <version>1.4.196</version>
    <scope>runtime</scope>
</dependency>

Шаблон запроса и пропускная способность

Мы используем h2 для загрузки некоторых данных для каждого запроса, затем выполняем несколько (около 50) запросов SELECT и, наконец, удаляем данные. Это приводит к постоянным вызовам 30k-40k в минуту (кроме нерабочих часов) в h2 (согласно новому мониторингу реликвий).

Каждая операция чтения получает новое соединение и освобождает его после выполнения.

EntityManager entityManager = null;
try {
     entityManager = entityManagerFactory.createEntityManager();
     Query query = entityManager.createNativeQuery(sqlQuery);
     query.setParameter("cartId", cartId);
     List<String> resultList = query.getResultList();
     return resultList;
} finally {
         if(null != entityManager) { entityManager.close(); }
}

Наблюдения

  • После перезапуска приложения загрузка пула минимальна, пока в один момент использование пула не резко возрастет и не достигнет максимального предела. Это происходит в течение 1-2 дней.
  • Как только пул достигает максимального предела соединения, количество заимствованных соединений увеличивается более быстрыми темпами по сравнению с числом возвращенных соединений, которое в остальном остается очень близко друг к другу.
  • В то же время количество заброшенных соединений также начинает увеличиваться вместе с журналами отмены.
  • Интересно, что время ответа на запрос остается тем же после исчерпания пула. Так что этот вид исключает медленный запрос.
  • Эта проблема возникает даже в самые неподходящие часы, когда трафик минимален. Так что это не имеет отношения к трафику.

Пожалуйста, направьте нас в правильном направлении, чтобы решить эту проблему.

UPDATE

Недавно мы обнаружили следующие причины в нашей трассировке стека, когда произошел один такой инцидент:

Причина: org.h2.jdbc.JdbcSQLException: база данных может быть уже в использование: ноль. Возможные решения: закрыть все остальные соединения; использовать режим сервера [90020-196]

Причина: java.lang.IllegalStateException: файл заблокирован: nio: /root/h2/cartdb.mv.db [1.4.196 / 7]

Вызывается: java.nio.channels.OverlappingFileLockException

Поэтому, углубившись в это, мы решили перейти в режим в памяти, поскольку нам не требуется сохранять данные после истечения времени жизни приложения. В результате блокировка файла не должна происходить, тем самым уменьшая или устраняя эту проблему.

Вернется и обновит в любом случае.

1 Ответ

0 голосов
/ 03 июня 2018

С момента последнего обновления по вопросу:

После длительного наблюдения производительности мы пришли к выводу, что использование H2 в файловом режиме (внедренном) каким-то образом приводило к периодическим исключениям блокировки файлов (хотя и нерегулярно).

Поскольку нашему приложению не требуется сохранять данные после истечения срока его службы, мы решили перейти в режим чистой памяти.

Хотя тайну исключения блокировки файла все еще нужно раскрыть.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...