我有一个配置了fixedDelay
或cron
的spring Scheduler任务,并且有该应用程序的多个实例在多个JVM上运行。
默认行为是所有实例都在执行调度程序任务。
有没有一种方法可以控制此行为,以便只有一个实例将执行调度程序任务,而其他实例则不执行。
如果您知道任何方法,请告诉我。
谢谢
答案 0 :(得分:1)
我们有类似的问题。我们这样修复它:
@Scheduled
bean。这样,我们可以确保计划的任务在我们的服务集群中仅执行一次。
答案 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确保您计划的任务最多同时执行一次。如果一个任务正在一个节点上执行,它会获得一个锁,该锁将阻止从另一个节点(或线程)执行同一任务。请注意,如果一个任务已经在一个节点上执行,则在其他节点上的执行不会等待,只需跳过它即可。