Spring batch Spring批处理:如何确保作业在运行时不允许同时再次运行

Spring batch Spring批处理:如何确保作业在运行时不允许同时再次运行,spring-batch,spring-batch-admin,Spring Batch,Spring Batch Admin,如何确保作业在运行时不允许同时再次运行 我们有一个需要1小时来处理提要和填充临时表的BJ。此BJ的第一步是清除临时表,并开始填充来自主存储前端表的数据 考虑这样一个场景:当BJ启动(第一次运行)时,如果我们再次启动BJ,它将从临时表中删除内容,作为第一步的一部分 因此,请建议我如何保持第二次执行直到第一次未完成?您可以设置spring batch Admin UI以查看作业的状态(失败/运行/完成等)。通过正确设置Spring Batch Admin UI,您甚至可以查看不同作业中多个任务的状态

如何确保作业在运行时不允许同时再次运行

我们有一个需要1小时来处理提要和填充临时表的BJ。此BJ的第一步是清除临时表,并开始填充来自主存储前端表的数据

考虑这样一个场景:当BJ启动(第一次运行)时,如果我们再次启动BJ,它将从临时表中删除内容,作为第一步的一部分


因此,请建议我如何保持第二次执行直到第一次未完成?

您可以设置spring batch Admin UI以查看作业的状态(失败/运行/完成等)。通过正确设置Spring Batch Admin UI,您甚至可以查看不同作业中多个任务的状态。

您可以创建自定义作为第一步,并在其中使用以查找所有任务。如果存在多个异常,则抛出异常。

在单个JVM中实现该异常应该能够使用二进制信号量。这将有助于避免同一作业的并行执行。如果您不想让第二个实例在设置了信号量值的情况下跳过执行,那么让第二个实例等待将有点棘手


您可以使用合适的“领导人选举”实现进行更复杂的序列化(包括跨Spring批处理节点)。我在我的项目中使用了Netflix Curator(一种Apache Zookeeper配方)。这里有几点提示:

我确信,这不是最好的解决方案,但我希望这将符合您的情况

执行作业时,请确保始终使用相同的参数运行作业。作业成功执行完成后,将调用脚本配置为删除与批处理作业执行相对应的条目

这样,它将给出错误,并且不允许您同时运行同一作业的两次执行。删除将确保允许串行执行

替代方法: 使用单个参数编写作业
作业执行id
。每次执行作业之前,从作业的批处理表中查询已完成作业的
作业执行id
的最大值。现在,使用递增1的
作业执行id
作为输入参数来执行作业


我认为这是一个比上面更好的方法。我不确定springbatch本身是否提供了实现此场景的任何简单的外卖选项。

也许我误解了您的问题,但是您可以通过在一个步骤中的Tasklet上指定
节流限制来限制任何单个步骤的并行执行次数。指定一个应确保一次只能执行一次:

<batch:step id="stepA" next="stepB">
  <batch:tasklet throttle-limit="1">
    <batch:chunk reader="myReader" writer="myWriter" commit-interval="100"/>
  </batch:tasklet>
</batch:step>

为此,我编写了一个特殊的递增器,它只在上一个作业执行完成时递增属性

    public class CompletedJobRunIdIncrementer extends RunIdIncrementer {
    private final JobRepository jobRepository;
    private final String jobName;

    public CompletedJobRunIdIncrementer(JobRepository jobRepository, String jobName) {
        this.jobRepository = jobRepository;
        this.jobName = jobName;
    }

    @Override
    public JobParameters getNext(JobParameters parameters) {
        JobExecution lastJobExecution = jobRepository.getLastJobExecution(jobName, parameters);
        return lastJobExecution == null || lastJobExecution.getStatus() == BatchStatus.COMPLETED ? super.getNext(parameters) : parameters;
    }
}
以及使用此递增器的作业:

jobBuilders.get("myJob").incrementer(new CompletedJobRunIdIncrementer(jobRepository, "myJob").start(someTask()).build()

您可以添加JobExecutionListener的自定义实现

下面是示例侦听器实现:

    @Component
    public class JobExecutionListener implements JobExecutionListener{


@Autowired
private JobExplorer jobExplorer;


@Override
public void beforeJob(JobExecution jobExecution) {
    int runningJobsCount = jobExplorer.findRunningJobExecutions(jobExecution.getJobInstance().getJobName()).size();
    if(runningJobsCount > 1){
        throw new RuntimeException("There are already active running instances of this job, Please cancel those executions first.");
    }
}

@Override
public void afterJob(JobExecution jobExecution) {

}

}

如果此作业的任何实例已在运行,则此操作将当前启动作业标记为失败。您可以根据业务需求处理此异常。

请参阅我的回答,了解我们已经设置了Spring Batch Admin。因此,请建议我如何保持第二次执行,直到第一次未按程序完成。所以第二个作业的执行直到第一个作业完成才开始有任何方法可以在Partitioner中实现,这样就可以在全局范围内完成。。。