首页 文章

重试Quartz Scheduler启动数据库连接失败

提问于
浏览
0

我们有一个Java应用程序,它使用Quartz来调度作业 . 我们使用的石英版本是:quartz-2.2.1

quartz配置使用JDBC作业存储 .

如果在石英调度程序对象上调用start方法时数据库连接已关闭(由于间歇性网络故障),则会因以下异常而失败:

2017-05-28 00:05:45 org.quartz.SchedulerConfigException: Failure occured during job recovery. [See nested exception: org.quartz.JobPersistenceException: Couldn't recover jobs: The connection is closed. [See nested exception: com.microsoft.sqlserver.jdbc.SQLServerException: The connection is closed.]]
2017-05-28 00:05:45     at org.quartz.impl.jdbcjobstore.JobStoreSupport.schedulerStarted(JobStoreSupport.java:692)
2017-05-28 00:05:45     at org.quartz.core.QuartzScheduler.start(QuartzScheduler.java:567)
2017-05-28 00:05:45     at org.quartz.impl.StdScheduler.start(StdScheduler.java:142)

为了确保石英调度程序成功启动,我们在代码中添加了重试,该代码在每1秒后调用石英调度程序对象上的start方法 . 但是当数据库连接启动时,对quartz scheduler start方法的调用成功(它不会抛出任何异常) - 但是不会启动驻留在数据库中的关联触发器,也不会触发任何作业 .

知道这里有什么问题吗?任何帮助将不胜感激 .

这是石英配置,请注意我们已启用验证查询来处理糟糕的连接(由于间歇性网络故障)

#============================================================================
# Configure Main Scheduler Properties  
#============================================================================

org.quartz.scheduler.instanceName = TestScheduler
org.quartz.scheduler.instanceId = AUTO
org.quartz.scheduler.skipUpdateCheck=true

#============================================================================
# Configure ThreadPool  
#============================================================================

org.quartz.threadPool.class =     org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount =  50
org.quartz.threadPool.threadPriority = 5

#============================================================================
# Configure JobStore  
#============================================================================

org.quartz.jobStore.misfireThreshold = 60000
org.quartz.jobStore.maxMisfiresToHandleAtATime = 15

org.quartz.jobStore.class =     org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.driverDelegateClass =     org.quartz.impl.jdbcjobstore.StdJDBCDelegate
org.quartz.jobStore.useProperties = false
org.quartz.jobStore.dataSource = aBPM
org.quartz.jobStore.tablePrefix = ABPM_
org.quartz.jobStore.isClustered = false
org.quartz.jobStore.useDBLocks = false
org.quartz.jobStore.acquireTriggersWithinLock = true

#============================================================================
# Configure Datasources  
#============================================================================
org.quartz.dataSource.aBPM.driver = org.hsqldb.jdbcDriver
org.quartz.dataSource.aBPM.URL = jdbc:hsqldb:file:embeddedDb/db/abpmquartz
org.quartz.dataSource.aBPM.user = sa
org.quartz.dataSource.aBPM.encryptPassword = yes
org.quartz.dataSource.aBPM.password = fMFVvEFk3gFmM9ewWQkTNg==
org.quartz.dataSource.aBPM.maxConnections = 55
org.quartz.dataSource.aBPM.validationQuery= SELECT 1

1 回答

  • 0

    您可能遇到job misfires的问题 .

    TL;DR: use appropriate misfire instructions when building your triggers, or increase misfireThreshold.


    如果调度程序在触发器应该触发时发生故障,则表示失败 . 调度程序启动后,Quartz会检查失误的作业并查找有关如何处理它们的说明 . 马上运行它们?等到下一次预定的开火时间?要让它知道该怎么做,您可以使用misfire instructions显式,或者只是默认使用Quartz的智能策略,这取决于触发类型(例如 CronTrigger 具有与 SimpleTrigger 不同的默认失火策略) .

    遗憾的是,Quartz的烹饪书在解释失火指令方面有点缺乏,并且如果您想了解更多信息,请告诉您检查每个 Trigger 子类的JavaDoc .
    因此,为了您的方便,这个人写了一篇带有all misfire instructions and default misfire policies explained的博客文章 .

    你没有告诉我们你正在使用什么样的触发器,但你可能想要 include misfire instructions like withMisfireHandlingInstructionFireNow() ,它会在调度程序启动后立即运行你的工作 .


    另一个选项是 set org.quartz.jobStore.misfireThreshold to a value higher ,而不是Scheduler启动的时间 .
    现在你把它设置为1分钟 . 这意味着任何比预期开火时间晚不到1分钟的工作,都不会被视为熄火,并且运行得很好 . 但是,对于迟到超过1分钟的工作,Quartz将检查他们的失火政策 .

    比如说,调度程序总是需要不到5分钟的时间上线;然后您可以尝试设置 org.quartz.jobStore.misfireThreshold = 300000 ,因此当调度程序启动时作业启动时,Quartz会发现它们迟到的时间不到5分钟,只是让它们执行而不先检查失火策略 .

相关问题