应用内的Spring Scheduler代码具有多个实例和多个JVM

时间:2018-08-08 07:25:06

标签: spring spring-boot scheduled-tasks spring-batch

我有一个配置了fixedDelaycron的spring Scheduler任务,并且有该应用程序的多个实例在多个JVM上运行。

默认行为是所有实例都在执行调度程序任务。

有没有一种方法可以控制此行为,以便只有一个实例将执行调度程序任务,而其他实例则不执行。

如果您知道任何方法,请告诉我。

谢谢

4 个答案:

答案 0 :(得分:1)

我们有类似的问题。我们这样修复它:

  1. 从我们的Spring Boot服务中删除了所有@Scheduled bean。
  2. 创建了具有所需时间表的AWS Lambda函数。
  3. Lambda函数通过调度请求进入我们的顶级域。
  4. 负载均衡器将此请求转发到服务实例之一。

这样,我们可以确保计划的任务在我们的服务集群中仅执行一次。

答案 1 :(得分:0)

我遇到过类似的问题,即同一计划的批处理作业在两台服务器上运行,而该服务器原本打算一次在一个节点上运行。但是后来我找到了一个解决方案,如果该作业已经在其他服务器上运行,则不执行该作业。

Job someJob = ...
Set<JobExecution> jobs = jobExplorer.findRunningJobExecutions("someJobName");
if (jobs == null || jobs.isEmpty()) {
        jobLauncher.run(someJob, jobParametersBuilder.toJobParameters());
    }
}

因此,在启动作业之前,需要检查该作业是否已在其他节点上执行。 请注意,这种方法仅适用于基于数据库的作业存储库。

答案 2 :(得分:0)

我们遇到了同样的问题,我们的三个实例每天执行相同的任务并执行三次任务。我们通过使用Spring批处理解决了这个问题。春季批处理只能具有唯一的作业ID,因此,如果您使用日期(如date)启动作业,它将限制重复的作业以相同的ID开始。在我们的案例中,我们使用的日期类似于“ 2020-1-1”(因为它每天仅运行一次)。这三个实例都尝试启动ID为'2020-1-1'的作业,但spring拒绝了两个重复的作业,表明作业'2020-1-1'已在运行。

答案 3 :(得分:0)

如果我对您的问题的理解是正确的,并且希望在单个实例上运行此计划的作业,那么我认为您应该查看ShedLock

ShedLock确保您计划的任务最多同时执行一次。如果一个任务正在一个节点上执行,它会获得一个锁,该锁将阻止从另一个节点(或线程)执行同一任务。请注意,如果一个任务已经在一个节点上执行,则在其他节点上的执行不会等待,只需跳过它即可。