배치에서는
ExecutionContext 라는 기능을 제공한다.
해당 기능을 이해하기 위해서는 전체적인 그림을 다시한번 짚고 넘어가야하는데
Job 은 Job Runner에서 시작이 된다. Job Runner는 잡의 이름과 파라미터를 전달 받아 실행시키는데
스크립트또는 명령을 통해 직접 잡을 실행할 때 사용
스프링을 *부트스트랩 해서 기동된 자바 프로세스 내에서 스케줄러를 사용해 잡을 실행 시킬때 사용. JobRegistry 를 샐성하는데 사용되는데 이 *JobRegistry 는 스프링이 부트스트랩 될때 실행 가능한 잡을 가지고 있다.
*부트스트랩 : 일반적으로 한번 시작되면 알아서 진행되는 일련의 과정
*JobRegistry : JobRegistry는 필수는 아니지만 context에서 Job을 추적하거나 다른 곳에서 생성된 Job을 application context의 중앙에 모을 때 유용하다.
등록된 Job의 이름과 속성들을 조작할 수 있으며 job name과 job instance의 Map의 형태로 이루워져 있다.
기본적으로 모든 Job타입의 빈을 기동시에 실행
(@deprecated since 2.3.0 in favor of {@link JobLauncherApplicationRunner})
로 구분된다.
Job Execution 은 잡의 실제 시도를 의미한다. 잡의 상태를 가지고 있으며 잡이 한번 실행이 됬다면 하나의
JobExcution 을 가지고 있다고 판단 할 수 있다.
Job Execution과 같이 Job의 상태를 알면 어떤 장점이 있을까?
바로 오류가 발생했을 때 해당 상태를 저장함으로써 실패한 시점부터 다시 처리가 가능하다.
Job Execution은 Job, Step 이 진행 될때 변경되고
Job 의 상태는 JobExecution의 Execution Context 에 저장된다.
Step Execution도 동일하게 Execution 을 가지게 된다.
ExecutionContext 는 기본적으로 배치 잡의 세션이다.
스프링 배치에서는 잡을 다루는 과정에서 실제로 여러개의 ExecutionContext가 존재할 수 있다.
스프링 배치는 잡이 처리되는 동안 각 청크를 커밋하면서 잡 또는 스텝의 상태를 저장한다.
구체적으로는 잡과 스텝의 현재 ExecutionContext 를 데이터베이스에 저장한다.
Job Execution vs Step Excution
ExecutionContext는 두개가 있다.
같은 기능을 가지고있으나 약간의 차이가 존재한다.
Execution Context 는 Job에서 사용하는 데이터를 보관하는 보관소이다.
즉, 언제나 Job 처리 시에 데이터를 보존, 추가, 갱신이 가능하다.
하지만 Step의 처리 결과나 값을 다음 Step에 전달하는 것은 불가하다.
하지만 Job Execution Context를 이용한다면 가능하다.
예시를 통해 보자.
@Bean
public Job multiStepJob(Step step1, Step step2, Step step3) {
return jobBuilderFactory.get("multiStepJob")
.incrementer(new RunIdIncrementer())
.start(step1)
.next(step2)
.next(step3)
.build();
}
@JobScope
@Bean
public Step step2() {
return stepBuilderFactory.get("step2")
.tasklet((contribution, chunkContext) -> {
System.out.println("step2");
ExecutionContext executionContext = chunkContext
.getStepContext()
.getStepExecution()
.getJobExecution()
.getExecutionContext();
executionContext.put("mykey", "mykey's value");
return RepeatStatus.FINISHED;
})
.build();
}
@JobScope
@Bean
public Step step3(){
return stepBuilderFactory.get("step3")
.tasklet((contribution, chunkContext) -> {
System.out.println("step3");
ExecutionContext executionContext = chunkContext
.getStepContext()
.getStepExecution()
.getJobExecution()
.getExecutionContext();
Object mykey = executionContext.get("mykey");
System.out.println(mykey);
return RepeatStatus.FINISHED;
})
.build();
}
하단 코드에 대해서 먼저 알아봐야하는데
ExecutionContext executionContext = chunkContext
.getStepContext()
.getStepExecution()
.getJobExecution()
.getExecutionContext();
Object mykey = executionContext.get("mykey");
Step Context -> Step Execution -> Job Execution -> Execution Context순으로 타고 들어가는것이다.
chunkContext는 트렌젝션의 단위라고 생각하면 된다.
지금 해당 코드는 JobExecution 에서 컨택스트를 받았기 때문에 Job ExcutionContext이다.
Step Execution 에서 Context로 들어가면 Step Execution Context인 것을 확인해야한다.
코드 실행 >>
Step2 스텝에서 설정한 Map을 확인하면
executionContext.put("mykey", "mykey's value");
이렇게 설정을 했고
Step3 스텝에서 이를 뱉는다.
Object mykey = executionContext.get("mykey");
System.out.println(mykey);
실행 해보면
이렇게 value 값을 잘 가져오는 것을 확인 할수 있다. 하지만
Job Execution 이 없이 Step Execution Context를 활용한다면?
ExecutionContext executionContext = chunkContext
.getStepContext()
.getStepExecution()
// .getJobExecution()
.getExecutionContext();
executionContext.put("mykey", "mykey's value");
ExecutionContext executionContext = chunkContext
.getStepContext()
.getStepExecution()
// .getJobExecution()
.getExecutionContext();
null값이 나오는 것을 확인 할 수 있다.
SpringBatch 스케줄러로 Job실행하기 (0) | 2022.08.19 |
---|---|
Spring Batch DB 데이터 이관하기 (0) | 2022.08.17 |
Spring Batch Listener (0) | 2022.08.16 |
Spring Batch 기본 예제. (0) | 2022.08.13 |
Spring Batch 란? (0) | 2022.08.12 |
댓글 영역