Проблема взаимоблокировки в DBCP, развернутой на Tomcat

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

Я обнаружил, что в DBCP 1.2.1, который я использовал, есть проблема с взаимоблокировкой, которая должна была быть решена в версии 1.4. Я обновился до 1.4, но проблема все еще не устранена.

В дампе потока есть много потоков, заблокированных следующей трассировкой стека наверху:

   java.lang.Thread.State: WAITING on org.apache.commons.pool.impl.GenericObjectPool$Latch@b6b09e
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Object.java:485)
at org.apache.commons.pool.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:1104)
at org.apache.commons.dbcp.PoolingDataSource.getConnection(PoolingDataSource.java:106)
at org.apache.commons.dbcp.BasicDataSource.getConnection(BasicDataSource.java:1044)
at org.springframework.jdbc.datasource.DataSourceTransactionManager.doBegin(DataSourceTransactionManager.java:200)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:350)
at org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(TransactionAspectSupport.java:261)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:101)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:160)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:89)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:631)

Любые предложения приветствуются!


person Iravanchi    schedule 19.04.2011    source источник
comment
У меня аналогичная проблема ... вы решили эту проблему ... не могли бы вы дать какой-нибудь указатель, если да ...   -  person Sudheer    schedule 25.02.2014
comment
Я тоже перешел на c3p0, остался очень доволен возможностями и стабильностью. С тех пор я не использовал DBCP, поэтому не могу сказать, существует проблема или нет.   -  person Iravanchi    schedule 28.02.2014


Ответы (5)


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

В некоторой степени связанный поток, Параметры пула соединений с JDBC: DBCP против C3P0. Ну, вообще-то я связал это.

[отредактировано, 19.10.12]

Tomcat 7 имеет приличный пул соединений, Пул соединений Tomcat JDBC.

person Adeel Ansari    schedule 19.04.2011
comment
В случае переключения пулов соединений как насчет jdbc-pool? DBCP показывает лучшую производительность в тестах по сравнению с c3p0, а jdbc-pool быстрее, чем оба. Есть опыт работы с этим? - person Iravanchi; 19.04.2011
comment
Нет, я никогда не использовал jdbc-pool. Следовательно, ничего не могу сказать по этому поводу. Но после прочтения это звучит многообещающе. Что касается производительности, эта ветка, people.apache.org /~fhanik/jdbc-pool/jdbc-pool.html указывает на низкую производительность DBCP. - person Adeel Ansari; 20.04.2011
comment
DBCP плохой по сравнению с jdbc-pool, но этот тест показывает, что c3p0 медленнее, чем оба (но, вероятно, более надежен, чем DBCP, как вы сказали): tomcatexpert.com/blog/2010/03/22/ - person Iravanchi; 20.04.2011
comment
В случае, если кто-то читает этот вопрос, я переключился на c3p0, как посоветовал @Adeel Ansari, и с тех пор у меня не было проблем с гораздо более высокими нагрузками (что было почти 1,5 года назад) - person Iravanchi; 16.10.2012

Вы убедились, что версия commons-pool соответствует версии dbcp?

Кроме того, я не вижу тупиковой ситуации в stacktrace, просто похоже, что у вас есть потоки, ожидающие освобождения соединений. Сколько потоков вы пытаетесь подключиться одновременно? Сколько подключений вы настроили для пула и т. Д.?

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

person Mikko Wilkman    schedule 19.04.2011
comment
Обе последние версии, DBCP 1.4, POOL 1.5.5. Также есть ошибка в POOL 1.5.2, которая показывает точно такую ​​же трассировку, что и моя, и ее нужно исправить в 1.5.3. А я использую 1.5.5. Я не настраивал параметры пула, поэтому использую значения по умолчанию. В нормальных условиях количество потоков обычно составляет от 30 до 50, но когда приложение блокируется, Tomcat создает поток для каждого запроса, и все они блокируются, поэтому он достигает 150 или 200 потоков. - person Iravanchi; 19.04.2011
comment
И ВСЕ потоки ожидают подключения после состояния тупика. Нет других потоков, которые что-либо активно делают. Все они в конечном итоге приходят к тому, что им требуется соединение, и они попадают в очередь, которая никогда не продвигается вперед. - person Iravanchi; 19.04.2011
comment
Хорошо, вы уверены, что действительно возвращаете соединения в пул? - person Mikko Wilkman; 19.04.2011
comment
Абсолютно. Я использую аспекты Spring в простой конфигурации (эффект можно увидеть в трассировке стека). И это не проблема при низком уровне параллелизма (с 10 или 20 пользователями). Я даже написал отладочный фильтр для подсчета открытий / закрытий в каждом потоке и проверки наличия утечек. - person Iravanchi; 19.04.2011
comment
Странно, но эта блокировка действительно происходит, когда пул исчерпан, и я бы не назвал это тупиком в такой ситуации ... Как обрабатывается закрытие соединения с помощью аспектов Spring? - person Mikko Wilkman; 19.04.2011
comment
Нет потока, занятого подключением, и все потоки ждут его. Думаю, проблема не в исчерпании пула. Аспект Spring TX возвращает (закрывает) соединение, когда вызываемый ниже метод каким-либо образом возвращается (либо возвращает, либо бросает). - person Iravanchi; 20.04.2011
comment
Я все еще уверен, что ситуация просто вызвана тем, что соединения не возвращаются в пул. Для этого больше не требуется, чтобы какой-либо поток фактически использовал это соединение. Возможно, вы могли бы проверить это, записав в журнал фактическое состояние пула (активные, незанятые и т. Д. Соединения), когда проблема существует? Если это показывает, что пул пуст, я бы продолжил отладку логики закрытия Spring TX и того, как она применяется к типу источника данных, который вы используете. - person Mikko Wilkman; 20.04.2011

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

Добавьте maxActive в свойствах источника данных и установите WHEN_EXHAUSTED_BLOCK на какое-то время, например 600ms - 1000ms. Вы получите No element available исключение только по прошествии 600-1000 мсек.

person arviarya    schedule 15.10.2012
comment
То, что вы описываете, замедляет работу. У меня был явный тупик (когда доступные соединения, которые возвращаются в пул, больше не обслуживаются), что было очевидно из дампа потока. Ни один из потоков ничего не делал, все они были заблокированы пулом. Вам следует более внимательно прочитать вопрос и ответы, прежде чем размещать ответ. - person Iravanchi; 16.10.2012

Я думаю, это вызвано тем, что вы не закрываете соединения в коде вашего приложения, поэтому у вас просто заканчиваются соединения в пуле. Возможно, вам стоит попробовать установить свойство removeAbandoned в DBCP. Это задокументировано в http://commons.apache.org/dbcp/configuration.html. в виде

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

Удачи!

person jcamillo    schedule 24.07.2012
comment
Нет, проблема не в том, что пул исчерпан. Я действительно создал обертки и подсчитал пары открытия / закрытия. Кроме того, при утечке соединения c3p0 тоже блокируется, причем довольно быстро (я это тестировал). Дамп потока ясно показывает, что потоки заблокированы друг для друга. - person Iravanchi; 24.07.2012

Я столкнулся с аналогичными проблемами, и это было решено следующими шагами

  1. Закройте все ресурсы базы данных в правильной последовательности

    resultSet.close();
    statement.close();
    connection.close();
    

Различные драйверы реализуются по-разному, некоторые драйверы все равно будут подключаться, если базовый набор результатов не закрыт.

  1. Необходимо настроить параметры Apache DBCP по умолчанию

dataSource.setDefaultAutoCommit(true);
dataSource.setMaxActive(700); // make sure db server has it 800 dataSource.setRemoveAbandoned(true); dataSource.setTestOnBorrow(true); dataSource.setLogAbandoned(true); dataSource.setTestWhileIdle(true); dataSource.setTestOnReturn(true); dataSource.setRemoveAbandonedTimeout(60);

Убедитесь, что сервер базы данных может разрешить как минимум 50+ подключений, количество которых превышает количество, указанное в setMaxActive, поскольку dbcp сначала предоставляет x новых подключения, а затем пытается очистить подключения, количество которых превышает setMaxActive. При очистке dbcp показывает, все подключения не были закрыты в журнале / консоли сервера.

person veer7    schedule 26.09.2017