2016-08-25 26 views
5

Tôi đã thiết lập nơi nhiều máy chủ chạy @Schedule chạy một công việc hàng loạt sẽ gửi email cho người dùng. Tôi muốn đảm bảo rằng chỉ một ví dụ của công việc này được chạy trên nhiều máy chủ.Thực hiện công việc đơn lẻ trên nhiều máy chủ

Dựa trên this câu hỏi Tôi đã thực hiện một số logic để xem liệu có thể giải quyết vấn đề này bằng cách sử dụng lô xuân không.

Để chạy một công việc mà tôi đã tạo ra một lớp helper JobRunner với các phương pháp sau:

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) { 
     ... 
    } 
} 

Các stopIfInactive phương pháp:

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); 
     } 
    } 
} 

Và sau đó các công việc đang chạy bằng cách sau đây trên tất cả các máy chủ:

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

Đây có phải là giải pháp hợp lệ cho nhiều máy chủ không thuc day? Nếu không, lựa chọn thay thế là gì?

EDIT 1

Tôi đã thử nghiệm hơn một chút - cài đặt hai ứng dụng mà chạy một @Schedule mỗi 5 giây mà khởi tạo một công việc bằng cách sử dụng lớp helper tôi tạo ra. Dường như giải pháp của tôi không giải quyết được vấn đề. Dưới đây là các dữ liệu từ batch_job_execution bảng được sử dụng bởi hàng loạt mùa xuân:

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) 

Tôi cũng đã thử phương pháp được cung cấp bởi @Palcente, tôi đã có kết quả tương tự.

+0

Bạn có thể giải thích những gì không hoạt động trong trường hợp trên không? Bạn có nghĩa là nhiều lần thực hiện cùng một công việc đang được chạy cùng một lúc? – DevG

+0

Có, cả hai máy chủ khởi động cùng một công việc cùng một lúc, mặc dù máy chủ vẫn chạy/bắt đầu trên một trong các nút. – Edd

Trả lời

0

Phiên bản mới nhất của Spring Integration đã thêm một số chức năng xung quanh ổ khóa được phân phối. Điều này thực sự là những gì bạn muốn sử dụng để đảm bảo rằng chỉ có một máy chủ kích hoạt công việc (chỉ có máy chủ có được khóa nên khởi động công việc). Bạn có thể đọc thêm về khả năng khóa của Spring Integration trong tài liệu tại đây: http://projects.spring.io/spring-integration/

+0

Tôi không thể tìm thấy bất kỳ ví dụ nào về tài liệu hoặc dự án mẫu tích hợp mùa xuân (https://github.com/spring-projects/spring-integration-samples) hiển thị chức năng này bằng cách sử dụng java-config. Tại thời điểm này tôi đang nghĩ đến việc tạo ra một bảng khóa đơn giản. – Edd

Các vấn đề liên quan