跨多个服务器执行单个作业

时间:2016-08-25 09:25:55

标签: java spring-boot spring-integration spring-batch

我设置了多个服务器运行@Schedule的位置,运行弹出批处理作业,向用户发送电子邮件。我想确保在多个服务器上只运行此作业的一个实例。

基于this问题 我已经实现了一些逻辑,看看是否可以仅使用弹簧批来解决这个问题。

要运行作业,我使用以下方法创建了一个帮助程序类JobRunner

public void run(Job job) {
    try {
        jobLauncher.run(job, new JobParameters());
    } catch (JobExecutionAlreadyRunningException e) {

        // Check if job is inactive and stop it if so.
        stopIfInactive(job);

    } catch (JobExecutionException e) {
        ...
    }
}

stopIfInactive方法:

private void stopIfInactive(Job job) {
    for (JobExecution execution : jobExplorer.findRunningJobExecutions(job.getName())) {
        Date createTime = execution.getCreateTime();

        DateTime now = DateTime.now();

        // Get running seconds for more info.
        int seconds = Seconds
                .secondsBetween(new DateTime(createTime), now)
                .getSeconds();

        LOGGER.debug("Job '{}' already has an execution with id: {} with age of {}s",
                job.getName(), execution.getId(), seconds);

        // If job start time exceeds the execution window, stop the job.
        if (createTime.before(now.minusMillis(EXECUTION_DEAD_MILLIS)
                .toDate())) {

            LOGGER.warn("Execution with id: {} is inactive, stopping",
                    execution.getId());

            execution.setExitStatus(new ExitStatus(BatchStatus.FAILED.name(),
                    String.format("Stopped due to being inactive for %d seconds", seconds)));

            execution.setStatus(BatchStatus.FAILED);
            execution.setEndTime(now.toDate());

            jobRepository.update(execution);
        }
    }
}

然后在所有服务器上运行以下作业:

@Scheduled(cron = "${email.cron}")
public void sendEmails() {
    jobRunner.run(emailJob);
}

这是多服务器设置的有效解决方案吗?如果没有,有哪些替代方案?

编辑1

我做了一些测试 - 设置两个应用程序,每5秒运行一次@Schedule,使用我创建的帮助程序类启动作业。似乎我的解决方案无法解决问题。以下是spring批处理使用的batch_job_execution表中的数据:

 job_execution_id | version | job_instance_id |       create_time       |       start_time        |        end_time         |  status   | exit_code | exit_message |      last_updated       | job_configuration_location
------------------+---------+-----------------+-------------------------+-------------------------+-------------------------+-----------+-----------+--------------+-------------------------+----------------------------
             1007 |       2 |               2 | 2016-08-25 14:43:15.024 | 2016-08-25 14:43:15.028 | 2016-08-25 14:43:16.84  | COMPLETED | COMPLETED |              | 2016-08-25 14:43:16.84  |
             1006 |       1 |               2 | 2016-08-25 14:43:15.021 | 2016-08-25 14:43:15.025 |                         | STARTED   | UNKNOWN   |              | 2016-08-25 14:43:15.025 |
             1005 |       2 |               2 | 2016-08-25 14:43:10.326 | 2016-08-25 14:43:10.329 | 2016-08-25 14:43:12.047 | COMPLETED | COMPLETED |              | 2016-08-25 14:43:12.047 |
             1004 |       2 |               2 | 2016-08-25 14:43:10.317 | 2016-08-25 14:43:10.319 | 2016-08-25 14:43:12.03  | COMPLETED | COMPLETED |              | 2016-08-25 14:43:12.03  |
             1003 |       2 |               2 | 2016-08-25 14:43:05.017 | 2016-08-25 14:43:05.02  | 2016-08-25 14:43:06.819 | COMPLETED | COMPLETED |              | 2016-08-25 14:43:06.819 |
             1002 |       2 |               2 | 2016-08-25 14:43:05.016 | 2016-08-25 14:43:05.018 | 2016-08-25 14:43:06.811 | COMPLETED | COMPLETED |              | 2016-08-25 14:43:06.811 |
             1001 |       2 |               2 | 2016-08-25 14:43:00.038 | 2016-08-25 14:43:00.042 | 2016-08-25 14:43:01.944 | COMPLETED | COMPLETED |              | 2016-08-25 14:43:01.944 |
             1000 |       2 |               2 | 2016-08-25 14:43:00.038 | 2016-08-25 14:43:00.041 | 2016-08-25 14:43:01.922 | COMPLETED | COMPLETED |              | 2016-08-25 14:43:01.922 |
              999 |       2 |               2 | 2016-08-25 14:42:55.02  | 2016-08-25 14:42:55.024 | 2016-08-25 14:42:57.603 | COMPLETED | COMPLETED |              | 2016-08-25 14:42:57.603 |
              998 |       2 |               2 | 2016-08-25 14:42:55.02  | 2016-08-25 14:42:55.023 | 2016-08-25 14:42:57.559 | COMPLETED | COMPLETED |              | 2016-08-25 14:42:57.559 |
(10 rows)

我也尝试过@Palcente提供的方法,我得到了类似的结果。

1 个答案:

答案 0 :(得分:1)

Spring Integration的最新版本增加了一些围绕分布式锁的功能。这实际上是您要用来确保只有一个服务器触发作业(只有获取锁的服务器才能启动作业)。您可以在此处的文档中阅读有关Spring Integration锁定功能的更多信息:http://projects.spring.io/spring-integration/