我们使用 Java Quartz 调度程序和 AWS RDS Aurora 集群作为底层数据存储。 RDS 配置为一个集群,具有一个主读/写数据库和一个只读副本。
当我在 AWS RDS 控制台中单击“实例操作 > 故障转移”时,当前写入者将成为读取者,只读副本将成为写入者。
但是在这种情况下,Quartz JDBC 数据源/连接池似乎无法处理故障转移,并且调度程序因以下错误而终止:
2018-08-22 13:10:21.106 ERROR 14824 --- [_ClusterManager] org.quartz.impl.jdbcjobstore.JobStoreTX : ClusterManager: Error managing cluster: Failure updating scheduler state when checking-in: The MySQL server is running with the --read-only option so it cannot execute this statement
org.quartz.JobPersistenceException: Failure updating scheduler state when checking-in: The MySQL server is running with the --read-only option so it cannot execute this statement
at org.quartz.impl.jdbcjobstore.JobStoreSupport.clusterCheckIn(JobStoreSupport.java:3468)
at org.quartz.impl.jdbcjobstore.JobStoreSupport.doCheckin(JobStoreSupport.java:3315)
at org.quartz.impl.jdbcjobstore.JobStoreSupport$ClusterManager.manage(JobStoreSupport.java:3920)
at org.quartz.impl.jdbcjobstore.JobStoreSupport$ClusterManager.run(JobStoreSupport.java:3957)
Caused by: java.sql.SQLException: The MySQL server is running with the --read-only option so it cannot execute this statement
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:127)
at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:95)
at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:122)
at com.mysql.cj.jdbc.ClientPreparedStatement.executeInternal(ClientPreparedStatement.java:960)
at com.mysql.cj.jdbc.ClientPreparedStatement.executeUpdateInternal(ClientPreparedStatement.java:1116)
at com.mysql.cj.jdbc.ClientPreparedStatement.executeUpdateInternal(ClientPreparedStatement.java:1066)
at com.mysql.cj.jdbc.ClientPreparedStatement.executeLargeUpdate(ClientPreparedStatement.java:1396)
at com.mysql.cj.jdbc.ClientPreparedStatement.executeUpdate(ClientPreparedStatement.java:1051)
at com.mchange.v2.c3p0.impl.NewProxyPreparedStatement.executeUpdate(NewProxyPreparedStatement.java:384)
at org.quartz.impl.jdbcjobstore.StdJDBCDelegate.updateSchedulerState(StdJDBCDelegate.java:2975)
at org.quartz.impl.jdbcjobstore.JobStoreSupport.clusterCheckIn(JobStoreSupport.java:3462)
... 3 common frames omitted
quartz.properties配置如下
org.quartz.dataSource.quartzDataSource.driver=com.mysql.cj.jdbc.Driver
org.quartz.dataSource.quartzDataSource.URL=jdbc:mysql://sqldbprd...:3306/quartz?useSSL=false
org.quartz.dataSource.quartzDataSource.user=quartz
org.quartz.dataSource.quartzDataSource.password=...
org.quartz.dataSource.quartzDataSource.maxConnections=5
org.quartz.dataSource.quartzDataSource.validationQuery=SELECT 1
org.quartz.dataSource.quartzDataSource.TestConnectionOnCheckin=false
org.quartz.dataSource.quartzDataSource.TestConnectionOnCheckout=true
相反,我们使用默认 HikariCP 配置的主要 Spring Boot API 继续工作,并且似乎拿起了写入器/读取器开关。
有人也遇到过这种情况吗? Quartz 可以配置为使用(现有的)HikariCP 而不是创建自己的数据源/池吗?如有任何建议,我们将不胜感激!
最佳答案
我在连接到 Aurora postgres 的 Spring Boot 应用程序中遇到了同样的问题。
JVM 缓存 DNS,并在故障转移后引用旧的(现在是读取器)实例。 您可以通过将以下行添加到应用程序的启动位置来将缓存设置为不同的值:
java.security.Security.setProperty("networkaddress.cache.ttl", "60");
我们遇到的另一个问题是我们不小心输入了数据库的实例 url,而不是集群 url。
了解更多信息:https://docs.aws.amazon.com/sdk-for-java/v1/developer-guide/java-dg-jvm-ttl.html
关于datasource - Quartz 调度程序不会在 AWS RDS 故障转移上更新数据库连接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51967956/