Spring Batch
: 대용량 일괄처리의 편의를 위해 설계된 Spring Boot 배치 프레임워크로, 배치 프로그램의 기본적 구성 요소인 로깅, 병렬처리, 대용량 데이터 처리를 위한 작업들을 제공한다.
Job & Step
스프링 배치의 가장 기본이 되는 구성요소로 Job 안에는 여러 Step이 존재하고, Step 안에 Tasklet 혹은 Reader & Processor & Writer 묶음이 존재하며 다음과 같은 예시를 들 수 있다.
JOB(name = "miracleMorning")
: 매일 아침 6시에 일어나면 커피를 마시고 운동을 간다 만약 그렇지 못하면 물을 마시고 운동을 간다
Step(name = "wakeUp")
: 일어난다
Step(name = "drinkCoffee")
: 커피를 마신다
Step(name = "drinkWater")
: 물을 마신다
Step(name = "exercise")
: 운동을 한다
이렇게 Job 을 선언하고 해당 Job을 수행하기 위한 Step 을 정의 한다
Tasklet vs Chunk
실제 처리 로직이 들어가 있는 빈이다. 스프링배치에 처리를 하는 방식은 크게 Chunk 방식과 Tasklet 방식으로 나눌수 있다. Chunk 방식은 세가지 클래스 빈 ItemReader, ItemProcessor, ItemWriter 를 구현하고 이미 스프링 배치에서 작성해놓은 클래스들이 있어 그것을 이용하면 된다. 물론 직접 상속받아 구현할 수도 있다. Tasklet 방식은 Tasklet 인터페이스만 구현하면 되고 개발자가 직접 작성한다. for loop 를 돌면 숫자를 출력하고 종료되면 RepeatStatus.FINISHED 를 반환 배치에 정상 종료를 전달한다
이제 위에서 정의한 예제를 직접 적용해보자!
Spring Batch 예제
먼저 batch 의존성을 추가해준다
implementation 'org.springframework.boot:spring-boot-starter-batch'
@SpringBootApplication 어노테이션이 붙은 파일에 @EnableBatchProcessing 을 붙여준다
@SpringBootApplication
@EnableBatchProcessing
public class AdvancedSpringApplication {
public static void main(String[] args) {
SpringApplication.run(AdvancedSpringApplication.class, args);
}
}
@Slf4j
@Configuration
@RequiredArgsConstructor
public class BatchJobConfig {
private final JobBuilderFactory jobBuilderFactory;
private final StepBuilderFactory stepBuilderFactory;
@Bean
public Job miracleMorning() {
return jobBuilderFactory.get("miracleMorning")
.start(wakeUp())
.on("COMPLETED")
.to(drinkCoffee())
.on("*")
.to(exercise())
.on("*")
.end()
.from(wakeUp())
.on("*")
.to(drinkWater())
.on("*")
.to(exercise())
.on("*")
.end()
.end().build();
}
@Bean
public Step wakeUp() {
return stepBuilderFactory.get("wakeUp")
.tasklet((contribution, chunkContext) -> {
log.info("----- wakeUp");
String result = "COMPLETED";
//Flow에서 on은 RepeatStatus가 아닌 ExitStatus를 바라본다.
if (result.equals("COMPLETED"))
contribution.setExitStatus(ExitStatus.COMPLETED);
else if (result.equals("FAIL"))
contribution.setExitStatus(ExitStatus.FAILED);
else if (result.equals("UNKNOWN"))
contribution.setExitStatus(ExitStatus.UNKNOWN);
return RepeatStatus.FINISHED;
})
.build();
}
@Bean
public Step drinkCoffee() {
return stepBuilderFactory.get("drinkCoffee")
.tasklet((contribution, chunkContext) -> {
log.info("----- drinkCoffee");
return RepeatStatus.FINISHED;
})
.build();
}
@Bean
public Step drinkWater() {
return stepBuilderFactory.get("drinkWater")
.tasklet((contribution, chunkContext) -> {
log.info("----- drinkWater");
return RepeatStatus.FINISHED;
})
.build();
}
@Bean
public Step exercise() {
return stepBuilderFactory.get("exercise")
.tasklet((contribution, chunkContext) -> {
log.info("----- exercise");
return RepeatStatus.FINISHED;
})
.build();
}
}
Spring Scheduler 적용
scheduler 의존성 주입을 해준다.
implementation 'org.springframework.boot:spring-boot-starter-quartz'
@SpringBootApplication 어노테이션이 붙은 파일에 @EnableScheduling 을 붙여준다
@SpringBootApplication
@EnableJpaAuditing
@EnableBatchProcessing
@EnableScheduling
public class AdvancedSpringApplication {
public static void main(String[] args) {
SpringApplication.run(AdvancedSpringApplication.class, args);
}
}
@Slf4j
@Component
@RequiredArgsConstructor
public class BatchSchedule {
private final JobLauncher jobLauncher;
private final BatchJobConfig batchJobConfig;
@Scheduled(cron = "*/5 * * * * *")
public void runJob() {
// job parameter 설정
Map<String, JobParameter> confMap = new HashMap<>();
confMap.put("time", new JobParameter(System.currentTimeMillis()));
JobParameters jobParameters = new JobParameters(confMap);
try {
jobLauncher.run(batchJobConfig.miracleMorning(), jobParameters);
} catch (JobExecutionAlreadyRunningException | JobInstanceAlreadyCompleteException
| JobParametersInvalidException | org.springframework.batch.core.repository.JobRestartException e) {
log.error(e.getMessage());
}
}
}
위 코드는 5초에 한번씩 miracleMorining batch를 실행하는 스케쥴러를 뜻한다 여기서 @Scheduled어노테이션 속성으로 붙는 cron은 반복 설정을 뜻하는데
*(에스더리스크) 를 앞에서부터 초(0-50) 분(0-50) 시간(0-23) 일(1-31) 월(1-12) 요일(0-7)을 의미한다.
참고로 요일에서 0과 7은 일요일이며 1부터 월요일이고 6은 토요일을 뜻한다.
끄읏 -!
참고
https://warpgate3.tistory.com/entry/Spring-Batch-Sample-Code-1