Соединение зависает после времени бездействия

в моем приложении Spring управляет пулом соединений для доступа к базе данных. Hibernate использует эти соединения для своих запросов. На первый взгляд у меня нет проблем с пулом: он корректно работает с параллельными клиентами и пулом только с одним подключением. Я могу выполнить много запросов, поэтому я думаю, что я (или Spring) не оставляю открытых соединений.

моя проблема появляется после некоторого времени бездействия (иногда 30 минут, иногда более 2 часов). Затем, когда спящий если поискать, он длится слишком долго. Установка уровня log4j для трассировки, я получаю эти журналы:

...
18:27:01 DEBUG nsactionSynchronizationManager  - Retrieved value [org.springframework.orm.hibernate3.SessionHolder@99abd7] for key [org.hibernate.impl.SessionFactoryImpl@7d2897] bound to thread [http-8080-Processor24]
18:27:01 DEBUG HibernateTransactionManager     - Found thread-bound Session [org.hibernate.impl.SessionImpl@8878cd] for Hibernate transaction
18:27:01 DEBUG HibernateTransactionManager     - Using transaction object [org.springframework.orm.hibernate3.HibernateTransactionManager$HibernateTransactionObject@1b2ffee]
18:27:01 DEBUG HibernateTransactionManager     - Creating new transaction with name [com.acjoventut.service.GenericManager.findByExample]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT
18:27:01 DEBUG HibernateTransactionManager     - Preparing JDBC Connection of Hibernate Session [org.hibernate.impl.SessionImpl@8878cd]
18:27:01 TRACE SessionImpl                     - setting flush mode to: AUTO
18:27:01 DEBUG JDBCTransaction                 - begin
18:27:01 DEBUG ConnectionManager               - opening JDBC connection

здесь он замерзает примерно на 2-10 минут. Но потом продолжает:

18:30:11 DEBUG JDBCTransaction                 - current autocommit status: true
18:30:11 DEBUG JDBCTransaction                 - disabling autocommit
18:30:11 TRACE JDBCContext                     - after transaction begin
18:30:11 DEBUG HibernateTransactionManager     - Exposing Hibernate transaction as JDBC transaction [jdbc:oracle:thin:@212.31.39.50:30998:orcl, UserName=DEVELOP, Oracle JDBC driver]
18:30:11 DEBUG nsactionSynchronizationManager  - Bound value [org.springframework.jdbc.datasource.ConnectionHolder@843a9d] for key [org.apache.commons.dbcp.BasicDataSource@7745fd] to thread [http-8080-Processor24]
18:30:11 DEBUG nsactionSynchronizationManager  - Initializing transaction synchronization
...

после этого он работает без проблем, до следующего периода неактивности. IMHO, похоже, пул соединений возвращает недопустимое / закрытое соединение, и когда Hibernate это понимает, попросите другое соединение с пулом.

Я не знаю, как я могу решить эту проблему или что я могу не ограничивают его. Любая помощь в достижении этого будет оценена.

спасибо.

EDIT: Ну, наконец, это было связано с правилом брандмауэра. База данных обнаруживает, что соединение потеряно, но пул (dbcp или c3p0) нет. Таким образом, он пытается запросить базу данных без успеха. Что все еще странно для меня, так это то, что период тайм-аута очень переменный. Возможно, правило специально странное или брандмауэр работает неправильно. Во всяком случае, у меня нет доступа к этой машине, и я могу только ждать объяснение. :(

5 ответов


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

в некоторых случаях брандмауэр отключает соединение таким образом, что конец JDBC не обнаруживает, и попытка использовать его приводит к неопределенному блоку.

в моем случае это был пользовательский пул соединений, который отправил тестовый запрос вниз по соединению, прежде чем вернуть его из пула. Я настроил это тестовый запрос для тайм-аута (using Statement.setQueryTimeout), чтобы он не блокировался бесконечно.


Проверьте конфигурацию вашей реализации пула. Обычно это Apache DBCP имеющего тайм-аут для каждого соединения после его закрытия.

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


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


вы должны добавить некоторые параметры в источник данных:

более важно добавить testOnBorrow и validationQuery


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

мы смогли обойти проблему, изменив свойство пула соединений testWhileIdle, которое предотвращает простаивание соединения и завершение работы брандмауэра. См.Apache commons dbcp BasicDataSource. Вот exert из файла конфигурации, persistentce-context.xml, который исправил проблему:

<property name="testWhileIdle">
  <value>true</value>
</property>
<property name="minEvictableIdleTimeMillis">
  <value>600000</value>
</property>
<property name="timeBetweenEvictionRunsMillis">
  <value>600000</value>
</property>

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

в нашем случае, вот некоторые из журналов, которые мы видели. Обратите внимание, что в этих журналах отладки потребуется 16 минут, чтобы открыть соединение, прежде чем соединение может быть использовано, и это то, что заставило все зависнуть. Ошибок, которые затрудняли бы поиск, не было.

09-06-13 @ 16:36:34 [DEBUG] HibernateTransactionManager - Preparing JDBC Connection of Hibernate Session [org.hibernate.impl.SessionImpl@db17ab]
09-06-13 @ 16:36:34 [DEBUG] ConnectionManager - opening JDBC connection
09-06-13 @ 16:52:00 [DEBUG] DataSourceUtils - Setting JDBC Connection
09-06-13 @ 16:52:00 [DEBUG] JDBCTransaction - begin
09-06-13 @ 16:52:00 [DEBUG] JDBCTransaction - current autocommit status: true