【问题标题】:Quartz Cluster recovery mechanismQuartz Cluster 恢复机制
【发布时间】:2026-01-18 05:25:01
【问题描述】:

我用 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 创建作业。 - 它给出了作业已经开始的错误。行为与我预期的一样。

3) 停止 APP1。我希望该作业将在 APP2 中执行,因为它仍然存在于 JobStore 中,但它没有。我需要提供一些额外的配置吗?

4) 启动APP1,也没有任何反应。此外,group1 和 key1 的记录仍然存在于 DB 中,无法启动。

我是否需要修改关闭行为以在应用程序关闭时删除作业并在另一个应用程序中启动作业?或者我只需要以另一种正确的方式配置触发器?

【问题讨论】:

    标签: quartz-scheduler


    【解决方案1】:

    我的错,这是一个愚蠢的问题。我忘记在我的应用程序中启动调度程序

    @Bean
    open fun schedulerFactory(): SchedulerFactory {
        val factory = StdSchedulerFactory()
        factory.initialize(ClassPathResource("quartz.properties").inputStream)
        factory.scheduler.start() // this line was missed
        return factory
    }
    

    【讨论】: