Spring/batch

[Spring-batch] Job 에 대해 알아보자!

jay Joon 2022. 2. 25. 13:39

기본개념

  • 배치 계층 구조에서 가장 상위에 있는 개념(하나의 배치작업 자체이다)
  • 적어도 하나 이상의 step을 포함하고 있는 컨테이너

기본 구현체

  • SimpleJob
    • 순차적으로 Step을 실행시키는 Job
    • 모든 Job에서 유용하게 사용할 수 있는 표준 기능을 갖고 있음
  • FlowJob
    • 특정한 조건과 흐름에 따라 Step을 구성하여 실행시키는 Job
    • Flow 객체를 실행시켜서 작업을 진행함

Job 은 어떻게 만들어지고 어떻게 실행되는 걸까??

대부분 JobBuilderFactory 을 이용하여 Job 생성하게 된다.

jobBuilderFactory.get("simpleJob") // job 의 이름을 정한다.
            .start(simpleStep1()) // 실행할 step 을  지정한다.
            .next(simpleStep2()) //  step 은 여러개 가질 수 있다.
            .build(); // 최종적으로 Job 을 생성한다.

Job 구현체 내부 stepList에 step을 순차적으로 저장하여 최종적으로 저장하여 생성하게 된다.


실행은 (스프링 부트 기준)

JobLauncherApplicationRunner 안에 있는 JobLauncher 를 이용하여 Job을 실행한다.

JobLauncher 는 인터페이스이며 실 구현체는 SimpleJobLauncher 를 이용한다.

다음처럼 SimpleJobLauncher 를 이용하여 등록한 Job을 step 별로 실행하게 된다.

추가적으로 publisher 가 등록되어있다면 job 이 실행되고 이벤트도 발행시킬 수 있습니다.

 

그렇다면 애플리케이션에 여러 개의 Job 등록되어있으면 어떻게 될까?

별 다른 설정을 하지 않고 애플리케이션을 실행하면 등록된 모든 Job을 실행하게 된다.

 

특정 job 만 실행시키고 싶다면 application.ymlspring.batch.job.names: ${job.name:NONE}

옵션을 추가하여 program arguments에 job 이름을 넣어주어 실행시켜주면 된다.

 

그렇다면 이 넘겨준 Job 이름은 어디서 사용되고 어떻게 한 가지 Job 만 실행되는 걸까?

 

Spring boot 가 실행될때 

JobLauncherApplicationRunner을 자동적으로 생성하여 등록하는 부분을 찾아보면 됩니다!

 

등록되는 Config 이름은 BatchAutoConfiguration 입니다.

코드를 보면 properties 또는 args로 넘겨준 jobName 이 있다면 생성할 때 runner에 등록을 합니다.

없다면 별다른 설정없이 생성됩니다.

 

이렇게 생성되었다면 JobLauncherApplicationRunner 가 실질적으로 SimpleJobLauncher 을 실행할 때 모든 Job을 실행할지 특정 Job 만 실행할지 결정하게 됩니다.

해당 메서드에서 executeLocalJobs , executeRegisteredJobs 두 개의 메서드가 불립니다.

 

여기서 executeLocalJobs 은 JobName 이 있다면 해당 job을 찾아 실행하게 됩니다.

그 후 executeRegisteredJobs 가 불리지만 JobLauncherApplicationRunner 에 jobName 이 설정되어 있다면 해당 메서드는 실행되지 않고 종료됩니다.

 

앞선 살펴본 코드를 요약하자면 다음과 같습니다.

  • jobName을 넘겨준다고 해서 해당하는 Job의 Bean 만 등록이 되는 것이 아니다.
  • 단지 jobName으로 여러 개의 job 들 중 이름이 같은 job 만 실행이 된다.

JobInstance, JobExecution에 대해 알아보자

JobExecution, JobInstance 는 위 그림과 같은 구조로 생성이 됩니다.

그림만으로도 충분히 이해하실 수 있지만 코드와 설명을 통해 조금 더 알아보죠!

JobInstance

  • Job 이 실행될 때마다 BATCH_JOB_INSTANCE에 저장할 Entity
  • 이미 동일한 JobParameter, JobName 이 존재하면 저장되지 않음
    • 중요) 저장이 안 된다는 거지 Job 실행이 안 되는 건 아닙니다.
  • 즉 동일한 Job에 대해서 JobParameter 가 다르다면 계속해서 생성됩니다.
  • 관계
    • Job (1) : JobInstance(N)
    • JobInstance (1) : JobParameter(1)

JobExecution

  • JobInstance 가 정상적으로 성공했는지? 아니면 실패했는지 기록합니다.
    • 성공시간, 시작시간 , Job 실행 상태 기록
    • 기록하는 테이블은 BATCH_JOB_EXECUTION입니다.
  • 관계
    • JobInstance (1) : JobExecution(N)

 

앞서 언급한 것 처럼 중요한 부분은 기존에 동일한 JobInstance 있다고 해서 실행하고자 하는

Job 이 무조건 실패하는 건 아닙니다.

(제가 처음 batch 을 접했을 땐 그런 줄 알았습니다. 😭)

 

 

이미 존재하는 JobInstance에 대해 동일한 Job, JobParameter을 실행시 다음과 같이 동작합니다.
(설명하는 내용은 JobInstance 존재하지 않아도 동일하게 검증을 진행합니다.)

 

첫 번째 검증

  • jobInstanceDao 로 부터 JobInstance 를 가져옵니다.
  • JobInstance 이용jobExecutionDao 으로부터 가장 마지막으로 등록된 JobExecution 가져옵니다.
  • 가져온 JobExecution 의 하위의 StepExecution 을 확인하여 실행을 할지 안 할지 결정합니다.
    • StepExecution 은 step을 설명할 때 다시 설명하도록 하겠습니다.

 

코드는 SimpleJobLauncher 의 run() 메서드를 따라가면서 보시면 됩니다.

해당 코드가 앞선 첫 번째 단계에 대해 설명한 부분입니다.

 

 

위 과정을 통과한다면 다시 다음과 같은 동작을 합니다.

 

 

두 번째 검증

  • jobInstanceDao 로 부터 JobInstance 를 가져옵니다.
  • JobInstance 이용 jobExecutionDao으로부터 등록된 모든 JobExecution 가져옵니다.
  • 모든 JobExecution 순회하며 상태를 확인하여 확인하여 실행을 할지 안 할지 결정합니다.
  • 위 과정이 이상이 없다면 새로운 jobExecution 을 만들어 저장합니다.

해당 코드는 SimpleJobLauncher run() 메서드 안의 jobRepository.createJobExecution 을 참고
하여 보시면 됩니다.

jobRepository의 구현체는 SimpleJobRepository 입니다.

 

 

해당 과정을 요약하자면

이미 등록된 JobInstance 가 존재하여도 jobExecution 의 상태에 따라 Job 실행 여부가 결정됩니다.



 

여기까지 Job 에 관련된 동작원리 및 속성에 대해 알아보았는데요!

모든 동작원리, 속성에 대해 설명하지 않았지만 제가 생각하는 중요한 부분은 짚고 넘어간거 같습니다.

혹시라도 글 본문에 잘못된 내용이 있거나 이 외에도 중요한내용이 있다면
댓글로 남겨주시면 반영하도록 하겠습니다.

 

감사합니다. 🙇‍♂️

 

 


 

참고: spring-batch reference