Tomcat 8.5 数据库故障转移后连接池未重新连接

Tomcat 8.5 Connection Pool not reconnecting after DB failover

我有一个使用 Tomcat 8.5 连接池、Java 8 和多可用区 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

并且 JDBC 连接 URL 具有这些参数:

autoreconnect=true&socketTimeout=20000

根据我的理解,validationQuery 应该失败并且连接被丢弃,因此应该创建一个新的正确连接。此外,根据 maxAge,10 分钟后所有连接都应该被丢弃并创建新连接。

即使在 20 分钟后,池也无法恢复。如前所述,我们必须重新启动 Tomcat 服务器。

是否有任何解释为什么池总是从故障转移中正确恢复,但在这种情况下却不能?

尝试在您的连接字符串中添加 ENABLE=Broken。 例如 : jdbc:oracle:thin:@(DESCRIPTION=(ENABLE=BROKEN)(ADDRESS=(PROTOCOL=tcp)(PORT=)(HOST=))(CONNECT_DATA=(SID=)))

我最终添加了一个解决此问题的 AWS RDS 代理。

我已经启动了一个小时的数据库故障转移,一切正常,中断时间不到 20 秒。而这个,不修改我的应用程序代码,只指向新的代理端点。