Пул подключений Tomcat 8.5 не подключается повторно после отработки отказа БД

У меня есть приложение, использующее пул соединений Tomcat 8.5, Java 8 и базу данных Multi-AZ AWS RDS MySQL. В последние годы у нас было несколько проблем с базой данных, которые привели к аварийному переключению. Когда происходило аварийное переключение, пул всегда мог обнаружить, что соединение было закрыто (после закрытия соединения запрещены никакие операции), и правильно переподключиться через минуту, когда резервный узел заработал.

Несколько дней назад у нас была отработка отказа, которая не следовала этому правилу. Из-за проблемы с базой данных оборудования база данных была недоступна, и произошло аварийное переключение. Затем, когда через пару минут резервный узел заработал, мы смогли правильно подключиться к базе данных из нашего настольного клиента MySQL.

Даже через несколько минут после отработки отказа и восстановления связи с базой данных приложение показало в журналах сотни исключений, например:

com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: No operations allowed after connection closed
...
Caused by: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure
...
The last packet successfully received from the server was 20,017 milliseconds ago.  The last packet sent successfully to the server was 20,016 milliseconds ago
...
Caused by: java.net.SocketTimeoutException: Read timed out
...

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

Наш пул настроен так:

initialSize = 5
maxActive = 16
minIdle = 5
maxIdle = 8
maxWait = 10000
maxAge = 600000
timeBetweenEvictionRunsMillis = 5000
minEvictableIdleTimeMillis = 60000
validationQuery = "SELECT 1"
validationQueryTimeout = 3
validationInterval = 15000
testOnBorrow = true
testWhileIdle = true
testOnReturn = false
jdbcInterceptors = "ConnectionState;StatementCache(max=200)"
defaultTransactionIsolation = java.sql.Connection.TRANSACTION_READ_COMMITTED

А URL-адрес подключения JDBC имеет следующие параметры:

autoreconnect=true&socketTimeout=20000

Насколько я понимаю, validationQuery должен был выйти из строя и соединение было разорвано, поэтому должно было быть создано новое правильное соединение. Кроме того, согласно maxAge, через 10 минут все соединения должны быть разорваны и созданы новые.

Бассейн не удалось восстановить даже через 20 минут. Как было сказано, нам пришлось перезапустить серверы Tomcat.

Есть ли какое-нибудь объяснение, почему пул всегда правильно восстанавливался после отработки отказа, но в данном случае это не удалось?


person IsidroGH    schedule 05.12.2020    source источник


Ответы (2)


Попробуйте добавить ENABLE = Broken в строку подключения. Например: jdbc: oracle: thin: @ (DESCRIPTION = (ENABLE = BROKEN) (ADDRESS = (PROTOCOL = tcp) (PORT =) (HOST =)) (CONNECT_DATA = (SID =)))

person BOSS Ben    schedule 06.12.2020
comment
Привет, БОСС, добро пожаловать в stackoverflow. При ответе на вопрос рекомендуется также включать краткое объяснение предложенного решения, это поможет другим пользователям понять проблему и решение. Спасибо - person funder7; 06.12.2020
comment
Спасибо, но это настройка Oracle. В моем случае я использую MySQL. - person IsidroGH; 06.12.2020

В итоге я добавил прокси AWS RDS, который решает эту проблему.

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

person IsidroGH    schedule 10.12.2020