Quartz Cluster 恢复机制
Quartz Cluster recovery mechanism
我 运行 一个带有 spring 的简单控制器来测试石英功能。
@PostMapping(path = ["/api/v1/start/{jobKey}/{jobGroup}"])
fun start(@PathVariable jobKey: String, @PathVariable jobGroup: String): ResponseEntity<String> {
val simpleJob = JobBuilder
.newJob(SampleJob::class.java)
.requestRecovery(true)
.withIdentity(JobKey.jobKey(jobKey, jobGroup))
.build()
val sampleTrigger = TriggerBuilder
.newTrigger()
.withIdentity(jobKey, jobGroup)
.withSchedule(
SimpleScheduleBuilder
.repeatSecondlyForever(5)
.withMisfireHandlingInstructionIgnoreMisfires())
.build()
val scheduler = factory.scheduler
scheduler.jobGroupNames.contains(jobGroup)
if (scheduler.jobGroupNames.contains(jobGroup)) {
return ResponseEntity.ok("Scheduler exists.")
}
scheduler.scheduleJob(simpleJob, sampleTrigger)
scheduler.start()
return ResponseEntity.ok("Scheduler started.")
}
@PostMapping(path = ["/api/v1/stop/{jobKey}/{jobGroup}"])
fun stop(@PathVariable jobKey: String, @PathVariable jobGroup: String): String {
val scheduler = factory.scheduler
scheduler.interrupt(JobKey.jobKey(jobKey, jobGroup))
val jobGroupNames = scheduler.jobGroupNames
logger.info("Existing jobGroup names: {}", jobGroupNames)
return scheduler.deleteJob(JobKey.jobKey(jobKey, jobGroup)).toString()
}
然后我使用相同的代码在不同的端口上启动两个应用程序并开始使用它。我们称它们为 APP1 和 APP2
我使用 PostgreSQL 作为 JobStore。
所以我运行几个场景。
1) 在APP1中用group1和key1创建job
2) 尝试在APP2中用group1和key1创建一个job。 - 它给出了作业已经开始的错误。行为符合我的预期。
3) 停止 APP1。我希望该作业将在 APP2 中执行,因为它仍然存在于 JobStore 中,但它没有。我需要提供一些额外的配置吗?
4) 启动APP1,也没有反应。此外,group1和key1的记录仍然存在于数据库中,无法启动。
我是否需要修改关闭行为以删除应用程序关闭时的作业并在另一个应用程序中启动作业?或者我只需要以另一种正确的方式配置触发器?
糟糕,这是个愚蠢的问题。我忘记在我的应用程序中启动调度程序
@Bean
open fun schedulerFactory(): SchedulerFactory {
val factory = StdSchedulerFactory()
factory.initialize(ClassPathResource("quartz.properties").inputStream)
factory.scheduler.start() // this line was missed
return factory
}
我 运行 一个带有 spring 的简单控制器来测试石英功能。
@PostMapping(path = ["/api/v1/start/{jobKey}/{jobGroup}"])
fun start(@PathVariable jobKey: String, @PathVariable jobGroup: String): ResponseEntity<String> {
val simpleJob = JobBuilder
.newJob(SampleJob::class.java)
.requestRecovery(true)
.withIdentity(JobKey.jobKey(jobKey, jobGroup))
.build()
val sampleTrigger = TriggerBuilder
.newTrigger()
.withIdentity(jobKey, jobGroup)
.withSchedule(
SimpleScheduleBuilder
.repeatSecondlyForever(5)
.withMisfireHandlingInstructionIgnoreMisfires())
.build()
val scheduler = factory.scheduler
scheduler.jobGroupNames.contains(jobGroup)
if (scheduler.jobGroupNames.contains(jobGroup)) {
return ResponseEntity.ok("Scheduler exists.")
}
scheduler.scheduleJob(simpleJob, sampleTrigger)
scheduler.start()
return ResponseEntity.ok("Scheduler started.")
}
@PostMapping(path = ["/api/v1/stop/{jobKey}/{jobGroup}"])
fun stop(@PathVariable jobKey: String, @PathVariable jobGroup: String): String {
val scheduler = factory.scheduler
scheduler.interrupt(JobKey.jobKey(jobKey, jobGroup))
val jobGroupNames = scheduler.jobGroupNames
logger.info("Existing jobGroup names: {}", jobGroupNames)
return scheduler.deleteJob(JobKey.jobKey(jobKey, jobGroup)).toString()
}
然后我使用相同的代码在不同的端口上启动两个应用程序并开始使用它。我们称它们为 APP1 和 APP2 我使用 PostgreSQL 作为 JobStore。
所以我运行几个场景。
1) 在APP1中用group1和key1创建job
2) 尝试在APP2中用group1和key1创建一个job。 - 它给出了作业已经开始的错误。行为符合我的预期。
3) 停止 APP1。我希望该作业将在 APP2 中执行,因为它仍然存在于 JobStore 中,但它没有。我需要提供一些额外的配置吗?
4) 启动APP1,也没有反应。此外,group1和key1的记录仍然存在于数据库中,无法启动。
我是否需要修改关闭行为以删除应用程序关闭时的作业并在另一个应用程序中启动作业?或者我只需要以另一种正确的方式配置触发器?
糟糕,这是个愚蠢的问题。我忘记在我的应用程序中启动调度程序
@Bean
open fun schedulerFactory(): SchedulerFactory {
val factory = StdSchedulerFactory()
factory.initialize(ClassPathResource("quartz.properties").inputStream)
factory.scheduler.start() // this line was missed
return factory
}