我有一个使用 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 服务器。
有什么解释为什么池总是从故障转移中正确恢复,但在这种情况下,它不能?