2016-08-25 53 views
5

我已经安装了多台服务器运行的一个@Schedule,它们运行向用户发送电子邮件的弹簧批处理作业。我想确保只有一个此作业的实例运行在多个服务器上。跨多个服务器执行单个作业

基于this问题 我已经实现了一些逻辑,看看它是否可能解决这个问题,只使用spring批处理。

运行我创建了一个辅助类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); 
} 

这是一个多服务器的有效解决方案s etup?如果不是,有什么选择?

编辑1

我做更多的测试 - 设置其运行每5秒一个@Schedule发起使用我创建的辅助类工作的两个应用程序。看来我的解决方案不能解决问题。下面是从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提供的方法,我已经得到了类似的结果。

+0

您能解释一下在上述情况下不起作用吗?你是说同时运行同一项工作的多次执行? – DevG

+0

是的,两台服务器同时启动相同的作业,即使它仍在其中一个节点上运行/启动。 – Edd

回答

0

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

+0

我无法找到有关使用java-config显示此功能的文档或弹簧集成示例(https://github.com/spring-projects/spring-integration-samples)项目的任何示例。目前我正在考虑创建一个简单的锁定表。 – Edd

相关问题