StepBuilderFactory
1. StepBuilderFactory
- StepBuilder를 생성하는 팩토리 클래스로서 get(String name) 메서드 제공
- StepBuilderFactory.get("stepName")으로 Step을 생성함
2. StepBuilder
- Step을 구성하는 설정 조건에 따라 다섯 개의 하위 빌더 클래스를 생성하고 실제 Step 생성을 위임한다.
- TaskletStepBuilder = TaskletStep을 생성하는 기본 빌더 클래스
- SimpleStepBuilder = TaskletStep을 생성하며 내부 저긍로 청크기반의 작업을 처리하는 ChunkOrientedTasklet 클래스를 생성
- PartitionStepBuilder = PartitionStep을 생성하며 멀티 스레드 방식으로 Job을 실행
- JobStepBuilder = JobStep을 생성하여 Step 안에서 Job을 실행
- FlowStepBuilder = FlowStep을 생성하여 Step 안에서 Flow를 실행
StepBuilder에서 제공되는 여러 종류의 API를 통해서 하위 구체적인 ~StepBuilder에게 위임하게 된다.
TaskletStep - 개념 및 API 소개
1. 기본개념
- 스프링 배치에서 제공하는 Step 의 구현체로서 Tasklet을 실행시키는 도메인 객체
- RepeatTemplate를 사용해서 Tasklet의 구문을 트랜잭션 경계 내에서 반복해서 실행함
- Task 기반과 Chunk 기반으로 나누어서 Tasklet을 실행함
2. Task vs Trunk 기반 비교
- 스프링 배치에서 Step의 실행단위는 크게 2가지로 나뉨
-- chunk 기반
--- 하나의 큰덩어리를 n개 씩 나눠서 실행한다는 의미로 대량처리를 하는 경우 효과적으로 설계됨
--- ItemReader , ItemProcessor, ItemWriter를 사용하며 청크 기반 전용 Tasklet인 ChunkOrientedTasklet 구현체가 제공된다.
-- Task 기반
--- ItemReader와 ItemWriter와 같은 청크 기반의 작업보다 단일 작업 기반으로 처리되는 것이 더 효율적인 경우
--- 주로 Tasklet 구현체를 만들어 사용
--- 대량 처리를 하는 경우 chunk 기반에 비해 더 복잡한 구현 필요
TaskletStep - tasklet()
1. 기본 개념
- Tasklet 타입의 클래스를 설정한다.
-- Tasklet
- step내에서 구성되고 실행되는 도메인 객체로서 주로 단일 태스크를 수행하기 위한 것
- TaskletStep에 의해 반복적으로 수행되며 반환값에 따라 계속 수행중 혹은 종료한다.
- RepeatStatus - Tasklet 의 반복 여부 상태 값
- RepeatStatus.FINISHED - Tasklet 종료 , RepeatStatus 을 null 로 반환하면 RepeatStatus.FINISHED 로 해석됨
- RepeatStatus.CONTINUABLE - Tasklet 반복
- RepeatStatus.FINISHED가 리턴되거나 실패 예외가 던져지기 전까지 TaskletStep 에 의해 while 문 안에서 반복적으로 호출 됨 (무한루프 주의)
- 익명 클래스 혹은 구현 클래스를 만들어서 사용한다.
- 이 메소드를 실행하게 되면 TaskletStepBuilder가 반환되어 관련 API를 설정할 수 있다.
- Step 에 오직 하나의 Tasklet 설정이 가능하며 두개 이상의 설정 했을 경우 마지막에 설정한 객체가 실행된다.
TaskletStep - startLimit() / allowStartIfComplete()
startLimit()
1. 기본 개념
- Step 의 실행 횟수를 조정할 수 있다.
- Step 마다 설정할 수 있다.
- 설정 값을 초과해서 다시 실행하려고 하면 StartLimitExceedException이 발생
- start-limit 의 디폴트 값은 Integer.MAX_VALUE
allowStartIfComplete()
1. 기본개념
- 재시작 가능한 job에서 Step 의 이전 성공 여부와 상관없이 항상 step을 실행하기 위한 설정
- 실행마다 유효성을 검증하는 Step이나 사전 작업이 꼭 필요한 Step등
- 기본적으로 COMPLETED 상태를 가진 Step 은 Job 재 시작시 실행하지 않고 스킵한다.
- allow-start-if-complete 가 "true" 로 설정된 step은 항상 실행한다.
TaskletStep 아키텍처
각 객체가 실행이 될때 중간 중간 생성 및 실행되는 것(StepExecution) 들을 확인하면 된다.
StepListener를 통해 befroeStep, afterStep등을 설정하여 특정시점에 호출하게 만들어줄 수 있다.
- AbstractStep#execute 메소드에서 이뤄진다.
getCompositeListener().beforeStep(stepExecution);
...
doExecute(stepExecution);
...
exitStatus = exitStatus.and(getCompositeListener().afterStep(stepExecution));
Tasklet이 끝났을때 특별한 응답값을 주지않으면 null 이 return 되는데 FINISHED와 같은의미로 해석됨
JobStep
1. 기본개념
- Job 에 속하는 Step 중 외부의 Job을 포함하고 있는 Step
- 외부의 Job이 실패하면 해당 Step이 실패하므로 결국 최종 기본 Job도 실패한다
- 모든 메타데이터는 기본 Job과 외부 Job 별로 각각 저장된다
- 커다란 시스템을 작은 모듈로 쪼개고 job의 흐름을 관리하고자 할때 사용할 수 있다
ParentJob 안의 JobStep 안에 ChildJob이 step1을 가지고 있고 또한 step2를 가지고 있다.
즉 ParentJob이 가진 Step은 JobStep, Step2 를 가지고 있다고 볼수 있다.
ChildJob의 step1 이 실패하면 ParentJob은 자신의 step이 실패한것이니까 최종적으로 실패하게 된다. 물론 ChildJob도 실패 한다. (JobExecution 에서)
ParentJob의 step2 가 실패하게되면 ChildJob은 성공했다고 나오지만 ParentJob만 실패했다고 Jobexecution table에 저장이 된다.
Step execution 테이블에도 jobStep ,step1 은 성공 , step는 실패가 나오게 된다.
@RequiredArgsConstructor
@Configuration
public class JobStepConfiguration {
private final JobBuilderFactory jobBuilderFactory;
private final StepBuilderFactory stepBuilderFactory;
@Bean
public Job parentJob() {
return this.jobBuilderFactory.get("parentJob")
.start(jobStep(null))
.next(step2())
.build();
}
@Bean
public Step jobStep(JobLauncher jobLauncher) {
return this.stepBuilderFactory.get("jobStep")
.job(childJob())
.launcher(jobLauncher)
.listener(new StepExecutionListener() {
@Override
public void beforeStep(StepExecution stepExecution) {
stepExecution.getExecutionContext().putString("name", "user1");
}
@Override
public ExitStatus afterStep(StepExecution stepExecution) {
return null;
}
})
.parametersExtractor(jobParametersExtractor())
.build();
}
@Bean
public Job childJob() {
return this.jobBuilderFactory.get("childJob")
.start(step1())
.build();
}
@Bean
public Step step1() {
return stepBuilderFactory.get("step1")
.tasklet(new Tasklet() {
@Override
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
// throw new RuntimeException("step1 was failed");
return RepeatStatus.FINISHED;
}
})
.build();
}
@Bean
public Step step2() {
return stepBuilderFactory.get("step2")
.tasklet(new Tasklet() {
@Override
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {
throw new RuntimeException("step2 was failed");
// return RepeatStatus.FINISHED;
}
})
.build();
}
@Bean
public DefaultJobParametersExtractor jobParametersExtractor() {
DefaultJobParametersExtractor extractor = new DefaultJobParametersExtractor();
extractor.setKeys(new String[]{"name"});
return extractor;
}
}
JOB_EXECUTION_PARAMS 테이블에서 116이 childJob에 해당하는 것이다. ParentJob의 ExecutionParams 도 물려 받았고 DefaultJobParametersExtractor를 통해 beforeStep listener에서 추가한 key, value값을 주입받을 수 있었던것이다.
'WEB > Spring Batch' 카테고리의 다른 글
스프링 배치 청크 프로세스 이해 (2) | 2023.03.22 |
---|---|
스프링 배치 실행 - Flow (0) | 2023.03.03 |
스프링 배치 실행 - Job (0) | 2023.02.23 |
스프링 배치 도메인 이해 (0) | 2023.02.17 |
스프링 배치 소개 + 시작 (0) | 2023.02.16 |