2016-08-25 47 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

相關問題