ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Spring Batch Skip Policy
    프로젝트/스프링 배치 튜토리얼 2023. 10. 12. 00:01
    728x90

    개요

    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

     

    댓글

Designed by Tistory.