datasource - Quartz 调度程序不会在 AWS RDS 故障转移上更新数据库连接

标签 datasource quartz-scheduler connection-pooling amazon-rds failover

我们使用 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/

相关文章:

java - quartz 触发器开始时间早于当前时间

local - 使用连接池时关闭 "local"OrientDB

connection-pooling - Java:跨其他 J2SE 应用程序共享连接池...?

java - spring mvc 3 和谷歌数据表

docker - Grafana + InfluxDB配置

c# - ASP.NET LinqDataSource WHERE 子句

sql - Grails:在普通的 groovy 类中获取数据源

java - quartz 在集群配置中的奇怪行为

scheduling - 如何在特定时间每天触发 akka scheduler?

java - mysql 和 javax.naming.NamingException