-
Spring Batch Skip Policy프로젝트/스프링 배치 튜토리얼 2023. 10. 12. 00:01728x90
개요
Spring Batch를 실행하다가 예외가 발생하면 어떻게 되는지 알아보고, 안정적인 Batch Application을 만들기 위해서 어떤 방안이 있는지 알아보고자 합니다.
예외가 간헐적으로 발생하는 Batch Application 구성
@Profile("skip-job") @Configuration class SkipJobConfig( private val jobRepository: JobRepository, private val batchTransactionManager: PlatformTransactionManager, ) { @Bean fun skipJob(): Job { return JobBuilder("skipJob job", jobRepository) .incrementer(RunIdIncrementer()) .start(chunkStep()) .build() } @Bean fun chunkStep(): Step { return StepBuilder("skipJob step", jobRepository) .chunk<String, String>(BATCH_SIZE, batchTransactionManager) .reader(beanReader()) .writer(ClassItemWriter()) .build() } @Bean fun beanReader(): ItemReader<String> { val data: List<String> = mutableListOf( "Byte", "Code", "Data", "Disk", "File", "Input", "Loop", "Logic", "Mode", "Node", "Port", "Query", "Ratio", "Root", "Route", "Scope", "Syntax", "Token", "Trace" ) logger.info ("Reading item: {}", data) return ListItemReader(data) } class ClassItemWriter: ItemWriter<String> { override fun write(itmes: Chunk<out String>) { logger.info("Writing item start") itmes.forEach { logger.info("Writing item : {}", it) if(it.contains('o')){ throw IllegalArgumentException("문자에 o가 들어가는 경우 예외를 만들면 어떻게 될까?") } } } } companion object { private const val BATCH_SIZE = 5 } }
예외와 함께 batch_job_execution table에 실패로 기록됩니다.
특정 예외가 발생했을 때 Skip 처리
@Bean fun chunkStep(): Step { return StepBuilder("skipJob step", jobRepository) .chunk<String, String>(BATCH_SIZE, batchTransactionManager) .reader(beanReader()) .writer(ClassItemWriter()) .faultTolerant() .skip(IllegalArgumentException::class.java) .skipLimit(20) .build() }
오류가 발생할 경우 장애를 처리하기 위한 기능을 제공하는 faultTolerant()를 선언합니다.
그리고 어떤 예외에서 skip을 수행할지 몇 번까지 허용할지에 대한 정책을 결정합니다.
위의 코드에서는 IllegalArgumentException에 대한 예외는 Skip 하고 최대 20번까지 허용합니다.
이제 더이상 오류가 발생해도 Step이 즉시 종료되지 않고 20번까지는 예외를 허용합니다.
작업을 수행하고 batch_step_execution 테이블의 데이터를 보면 11번의 write_skip_count를 가지며 작업은 성공적으로 끝났음을 알 수 있습니다.
예외를 핸들링하는 SkipPolicy 구현
@Configuration class CustomSkipPolicy : SkipPolicy { companion object { private const val MAX_SKIP_COUNT = 10 } override fun shouldSkip(throwable: Throwable, skipCount: Long): Boolean { if (throwable is IllegalArgumentException && skipCount < MAX_SKIP_COUNT) { return true } return false } } @Bean fun chunkStep(): Step { return StepBuilder("skipJob step", jobRepository) .chunk<String, String>(BATCH_SIZE, batchTransactionManager) .reader(beanReader()) .writer(ClassItemWriter()) .faultTolerant() // .skip(IllegalArgumentException::class.java) // .skipLimit(20) .skipPolicy(CustomSkipPolicy()) .build() }
조금 더 정교한 SkipPolicy를 위해서 Spring Batch에서는 SkipPolicy 인터페이스를 제공합니다.
Skip 조건을 직접 구현할 수 있습니다.
이번에는 10번 허용하도록 해보겠습니다.
위에서는 11번의 Skip이 발생했으므로 CustomSkipPolicy를 적용하게 되면 Step은 실패해야 합니다.
예상대로 실패하게되고 SKIP_COUNT를 20으로 늘리면 다시 성공합니다.
참고자료
https://www.baeldung.com/spring-batch-skip-logic
'프로젝트 > 스프링 배치 튜토리얼' 카테고리의 다른 글
Spring Batch 데이터베이스와 함께 사용하기 (0) 2023.10.11 Spring Batch 프로젝트 생성하기 - Spring Boot 3.1 (0) 2023.10.09 JobParameters Intellij 환경 변수 설정 (0) 2023.02.14 SpringBatch Cursor 기반 vs Paging 기반 (0) 2023.02.07 Spring Batch 프로젝트 생성하기 - Spring Boot 2.7.5 (0) 2023.02.05