WebApp (Tomcat-jdbc) Объединенное исключение блокировки подключения к базе данных
Я некоторое время просматривал SO и пережевывал шляпу в процессе, но не могу найти точное совпадение с моей проблемой.
Короче говоря, я получаю превосходную трассировку стека (org.apache.tomcat.jdbc.pool.ConnectionPool) после 60 секунд бездействия, что является нормальным поведением для нескольких потоков на стороне сервера.
Я использую Tomcat JDBC Connection Pooling (org.apache.tomcat.jdbc.pool.DataSource) напрямую
Трассировка стека:
Oct 29, 2012 8:55:50 PM org.apache.tomcat.jdbc.pool.ConnectionPool abandon
WARNING: Connection has been abandoned PooledConnection[[email protected]]:java.lang.Exception
at org.apache.tomcat.jdbc.pool.ConnectionPool.getThreadDump(ConnectionPool.java:967)
at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:721)
at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:579)
at org.apache.tomcat.jdbc.pool.ConnectionPool.getConnection(ConnectionPool.java:174)
at org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.java:111)
at com.getsom.getConnection(DAO.java:1444)
at com.getsom.PreparedConnection.(PreparedConnection.java:48)
at com.getsom.Alarms.run(Alarms.java:492)
Мои свойства PoolProperties настроены следующим образом:
PoolProperties pp = new PoolProperties();
pp.setUrl( someValidUrl);
pp.setDriverClassName("com.mysql.jdbc.Driver");
pp.setUsername( someUser);
pp.setPassword( somePassword);
pp.setJmxEnabled( true);
pp.setTestWhileIdle( true);
pp.setTestOnBorrow( true);
pp.setValidationQuery( "SELECT 1");
pp.setTestOnReturn( false);
pp.setValidationInterval(30000);
pp.setTimeBetweenEvictionRunsMillis(30000);
pp.setMaxActive(100);
pp.setInitialSize(10);
pp.setMaxWait(10000);
pp.setMinEvictableIdleTimeMillis(30000);
pp.setMinIdle(10);
pp.setLogAbandoned(true);
pp.setRemoveAbandoned(true);
pp.setRemoveAbandonedTimeout(60);
pp.setJdbcInterceptors("org.apache.tomcat.jdbc.pool.interceptor.ConnectionState;"+
"org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer");
setPoolProperties(pp);
Я надеялся, что setValidationInterval (30000) спасет меня, поскольку 30-е годы не так много в жизненном цикле связи. В любом случае, вопрос:
Что мне не хватает, чтобы поддерживать это соединение навсегда?
Приятно знать: почему я тайминг в функции, которая заявила о соединении, хотя она была вызвана на 30 секунд раньше.
Ответы
Ответ 1
Несмотря на то, что я нахожусь на 1 год позже на этой странице, я все же споткнулся, потому что у меня возникли подобные проблемы, и мне тоже нужно решение. Поэтому я думал, что поделюсь тем, что в конечном итоге сработало для меня.
В моем случае, после поиска и чтения этой статьи → > configuring-jdbc-pool-high-concurrency - я просто добавил такой перехватчик в конфигурацию моего пула;
"org.apache.tomcat.jdbc.pool.interceptor.ResetAbandonedTimer"
чтобы строка (из вашего опубликованного кода выше), где вы делаете setJdbcInterceptors(...)
, теперь должна выглядеть следующим образом:
p.setJdbcInterceptors(
"org.apache.tomcat.jdbc.pool.interceptor.ConnectionState;"
+ "org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer;"
+ "org.apache.tomcat.jdbc.pool.interceptor.ResetAbandonedTimer");
Объяснение. В цитате из статьи говорится:
Мы хотим убедиться, что когда мы обнаруживаем, что соединение все еще используется, мы reset таймер тайм-аута, чтобы соединение не считалось заброшенным. Мы делаем это, вставляя перехватчик.
Каждый раз, когда оператор готов или выполняется запрос, таймер будет reset таймером останова в пуле подключений. Таким образом... выполнение большого количества запросов и обновлений не будет тайм-аутом.
Принимая во внимание, что вы, скорее всего, давно преодолели проблему, я все еще надеюсь, что это поможет кому-то еще иметь похожие проблемы, которые сталкиваются с этой страницей, как и я.
Ура!
Ответ 2
Вы видели информацию на веб-сайте Tomcat, относящуюся к PoolConnection. Возможно, вам нужно посмотреть на свойство minEvictableIdleTimeMillis
Чтобы ответить на ваш вопрос, вы выбрали время, потому что вы проверяете простоя и отказываетесь от подключений каждые 30 секунд (см. TimeBetweenEvictionRunsMillis
), и поскольку вы устанавливаете вычитаемый тайм-аут простоя через 30 секунд (см. minEvictableIdleTimeMillis
), вы заканчиваете с тем, что у вас есть. Вы сказали, что получаете это исключение в режиме ожидания, я подозреваю, что это исключение является результатом закрытия простоя соединения, а не отказа от подключения. По моему мнению, отказ от подключения используется для выключения более длинных ожиданий (в отличие от простоя соединений).
Лично я не хотел бы иметь связи живыми навсегда, потому что они будут потреблять ресурсы (то есть соединение с db) без необходимости. Я бы играл с моими максимальными соединениями, выселениями и простоями, чтобы оптимизировать свои собственные требования. Я думаю, вы можете установить эти значения достаточно большими, чтобы они были навсегда! Это действительно зависит от того, что вы делаете, хотя...
Извините, я больше не мог помочь.
Ответ 3
Просто добавьте следующую запись в tomcat7 conf/server.xml или в context.xml, где присутствует ваш тег ресурса.
jdbcInterceptors="org.apache.tomcat.jdbc.pool.interceptor.ConnectionState;
org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer;
org.apache.tomcat.jdbc.pool.interceptor.ResetAbandonedTimer"
Ответ 4
track 'removeAbandonedTimeout' в файле конфигурации. это должен быть максимальный запуск запроса в приложении. в противном случае он будет закрывать соединение в середине выполнения
Ответ 5
Если вы определяете свой источник данных в файле context.xml tomcat, вы должны добавить ResetAbandonedTimer, как показано ниже:
jdbcInterceptors="ConnectionState;StatementFinalizer;ResetAbandonedTimer"
После установки ResetAbandonedTimer проблема разрешилась в моем приложении, попросив сообщить мне, существует ли какая-либо связь между перехватчиком ResetAbandonedTimer и removeAbandoned = "true" removeAbandonedTimeout = "60"
Ответ 6
Ответы на этот вопрос были очень полезны для меня.
Хотя в моем случае у меня уже был настроен перехватчик JDBC "ResetAbandonedTimer".
Однако у меня был запрос, который выполнялся дольше, чем "removeAbandonedTimeout", который я также настроил. Как только я увеличил "removeAbandonedTimeout", проблема исчезла.
Ответ 7
Была похожая проблема, т.е. Tomcat закрывал соединение JDBC из-за того, что оно было прервано из-за того, что транзакция заняла много времени.
Решил это, осознав, что abandoned
и idle
различны, и установив: spring.datasource.tomcat.removeAbandonedTimeout: 86400 #seconds
Ответ 8
Я вижу, что эта ветка старая, но у меня была похожая проблема, и в конце концов я нашел причину, которая ее вызвала, поэтому я хотел бы поделиться, если она может кому-то помочь:
Я использовал соединение из спокойного веб-сервиса. В интерфейсе на стороне сервера, обрабатывающем запрос от клиента, я случайно добавил "throws IOException" в сигнатуру метода:
@GET
@Path("/databases")
@Produces(MediaType.APPLICATION_JSON)
public String getAllDatabases() throws IOException {