Spring, Spring Boot/Batch

Spring Batch 병렬 처리

너지살 2023. 8. 23. 21:01

Spring Batch 병렬 처리

 

 

 

Spring Batch 병렬 처리 

Spring Batch는 대용량 데이터를 처리하는 프레임워크 입니다.

병렬 처리는 한 번에 여러 작업을 동시에 실행하여 작업을 분산시키는 방법이며 성능 향상을 위한 중요한 기능 중 하나 입니다. 

이번에는 TaskExecutor를 사용하여 step 내부를 Chunk 단위로 병렬 처리한 경험을 기록하려 합니다. 

 

 

 

스레드 풀 설정

Spring Batch 병렬 처리를 위해 스레드 풀 설정을 진행합니다. 

    @Bean
    public TaskExecutor taskExecutor() {
        ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
        taskExecutor.setCorePoolSize(4); // 코어 스레드 개수 설정
        taskExecutor.setMaxPoolSize(8); // 최대 스레드 개수 설정
        taskExecutor.setQueueCapacity(10); // 큐 크기 설정
        return taskExecutor;
    }

 

 

ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor(); 

ThreadPoolTaskExecutor 클래스는 Spring의 TaskExecutor 인터페이스를 구현한 것으로 다중 스레드를 관리하고 작업을 실행하는데 사용됩니다. 이 코드를 통해 병렬 처리를 활성화하고 다수의 스레드를 사용하여 작업을 분산 처리할 수 있게 합니다. 

 

taskExecutor.setCorePoolSize(4); 

이 메소드를 통해 코어 스레드 개수를 설정합니다. 

코어 스레드 개수는 동시에 실행되는 스레드의 최소 개수를 나타냅니다.

일반적으로 CPU의 코어 수 만큼 코어 스레드를 설정합니다. 

 

taskExecutor.setMaxPoolSize(8); 

이 메소드를 통해 허용되는 최대 스레드 개수를 설정합니다. 

최대 스레드 개수는 동시에 실행되는 스레드의 최대 개수를 나타냅니다.

작업 부하가 증가하면서 새로운 작업이 큐에 추가될 때 최대 스레드 개수까지 스레드가 생성될 수 있습니다. 

최대 스레드 개수를 초과하는 작업은 큐에 대기하게 됩니다. 

 

taskExecutor.setQueueCapacity(10); 

이 메소드를 통해 작업 큐의 최대 크기를 설정합니다. 

작업 큐 크기는 대기 중인 작업을 보관하는 큐의 최대 용량을 나타냅니다.

스레드 풀의 코어 스레드 수와 큐 크기를 조절하여 일정 부하를 유지하도록 설정합니다. 

 

 

이러한 설정을 통해 적절한 코어 스레드 개수와 큐 크기를 조절하여 작업의 처리량과 작업 큐의 부하를 효과적으로 관리할 수 있습니다. 

 

 

 

설정한 TaskExecutor 적용

    @Bean
    public Step userTierStepV2() {
        return stepBuilderFactory.get("userStepV2")
                .<User, User>chunk(100)
                .reader(jpaPagingItemReaderV2())
                .processor(userProcessorV2())
                .writer(jpaItemWriterV2())
                .taskExecutor(taskExecutor()) // taskExecutor 적용
                .build();
    }

 

.taskExecutor(taskExecutor())

이 메소드를 통해 설정한 TaskExecutor를 적용하여 병렬 처리, 분산 처리를 가능하게 합니다. 

 

 

 

성능 비교

v1 : 기존 방식 / v2 : 병렬 처리 방식

 

 

기존 방식

2023-08-23 22:40:13.189  INFO 13572 --- [nio-8080-exec-6] o.s.b.c.l.support.SimpleJobLauncher      : Job: [SimpleJob: [name=userJobV1]] launched with the following parameters: [{time=1692798013181}]
2023-08-23 22:40:13.196  INFO 13572 --- [nio-8080-exec-6] o.s.batch.core.job.SimpleStepHandler     : Executing step: [userStepV1]
2023-08-23 22:40:19.935  INFO 13572 --- [nio-8080-exec-6] o.s.batch.core.step.AbstractStep         : Step: [userStepV1] executed in 6s739ms
2023-08-23 22:40:20.008  INFO 13572 --- [nio-8080-exec-6] o.s.b.c.l.support.SimpleJobLauncher      : Job: [SimpleJob: [name=userJobV1]] completed with the following parameters: [{time=1692798013181}] and the following status: [COMPLETED] in 6s794ms
2023-08-23 22:40:20.008  INFO 13572 --- [nio-8080-exec-6] com.dotd.user.aop.LoggingAspect          : 위치 : BatchController.setTier() / 걸린 시간 :  6827 ms

 

 

병렬 처리 

2023-08-23 22:42:05.646  INFO 13572 --- [nio-8080-exec-9] o.s.b.c.l.support.SimpleJobLauncher      : Job: [SimpleJob: [name=userJobV2]] launched with the following parameters: [{time=1692798125638}]
2023-08-23 22:42:05.652  INFO 13572 --- [nio-8080-exec-9] o.s.batch.core.job.SimpleStepHandler     : Executing step: [userStepV2]
2023-08-23 22:42:07.024  INFO 13572 --- [nio-8080-exec-9] o.s.batch.core.step.AbstractStep         : Step: [userStepV2] executed in 1s372ms
2023-08-23 22:42:07.028  INFO 13572 --- [nio-8080-exec-9] o.s.b.c.l.support.SimpleJobLauncher      : Job: [SimpleJob: [name=userJobV2]] completed with the following parameters: [{time=1692798125638}] and the following status: [COMPLETED] in 1s380ms
2023-08-23 22:42:07.028  INFO 13572 --- [nio-8080-exec-9] com.dotd.user.aop.LoggingAspect          : 위치 : BatchController.setTierVersionTwo() / 걸린 시간 :  1390 ms

 

chunk 사이즈 100개로 데이터 10000건을 대상으로 사용자의 사용 금액에 따라 등급을 정하는 로직을 돌렸을 때 나온 결과 입니다. 

기존 처리 방식은 6827ms 인 반면 병렬 처리한 방식은 1390ms로 눈에 띄게 빨라진걸 확인할 수 있습니다.

병렬 처리 방식은 데이터 건수가 많을수록 그 성능차이가 더 크게 나타납니다. 

 

 

 

마무리

이번에는 TaskExecutor로 멀티 스레드로 Batch를 처리하도록 했습니다. 

병렬 처리를 적용하여 기존 방식과 비교한 결과 눈에 띄게 빨라진 것을 확인했으며 대용량 데이터를 처리할 때 성능 향상에 중요한 역할을 한다는 것을 배웠습니다.

하지만 이것으로 끝이 아닙니다. Spring Batch는 flow, split을 지원하여 작업의 흐름을 설정할 수 있으며 어떤 작업들을 병렬 처리할 것인지 배치할 수 있습니다.

다음 글에는 flow, split를 활용해 작업 흐름을 설정해보도록 하겠습니다. 

 

 

 

 

참고 사이트

https://devfunny.tistory.com/833

 

[SpringBatch 실습] 31. 스프링 배치 Parallel Steps(병렬) 수행하여 분석

Parallel Steps SplitState를 사용하여 여러개의 Flow들을 병렬적으로 실행하는 구조이다. 실행이 다 완료된 후 FlowExecutionStatus 결과들을 취합해서 다음 단계를 결정한다. Job 생성 ParallelStepConfiguration.java

devfunny.tistory.com