Spring Boot 비동기 서비스 만들기(@Async)

By | 2021년 12월 18일
Table of Contents

Spring Boot 비동기 서비스 만들기(@Async)

참조

로그 저장 로직을 비동기로 해 놓으면, 서비스 속도 저하가 없어,
서비스 품질 향상에 도움이 된다.

@Configuration

CorePoolSize : 기본 실행 대기하는 Thread의 수
MaxPoolSize : 동시 동작하는 최대 Thread의 수
QueueCapacity : MaxPoolSize 초과 요청시 최대 수용 가능한 Queue의 수

@Configuration
@EnableAsync
public class AsyncConfig extends AsyncConfigurerSupport {

    public Executor getAsyncExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(2);
        executor.setMaxPoolSize(10);
        executor.setQueueCapacity(500);
        executor.setThreadNamePrefix("mg-async-");
        executor.initialize();

        return executor;
    }
}

@Async

@Async 애너테이션 추가만으로 비동기 서비스가 된다.

@RequiredArgsConstructor
@Service
public class LoggerService {

    private final LogKakaoRestaurantInfoRepository repository;
    private final LogKakaoRestaurantInfoMapper mapper = Mappers.getMapper(LogKakaoRestaurantInfoMapper.class);

    @Async
    @Transactional
    public void saveKakaoRestaurantInfo(List<Document> documents) {
        for (Document document : documents) {
            try {
                LogKakaoRestaurantInfo info = repository.getById(document.getId());
                mapper.updateFromDto(document, info);
            } catch (EntityNotFoundException ex) {
                repository.save(mapper.toEntity(document));
            }
        }
    }
}

주의사항

  1. private method 사용 불가

  2. self-invocation(자가 호출) 불가

    같은 Class 에 존재하는 method 에 @Async Annotation을 붙여도 동기방식으로 작동한다.

  3. QueueCapacity 초과 요청에 대한 비동기 method 호출시 방어 코드 작성 필요

QueueCapacity 를 모두 소진한 경우, TaskRejectedException 이 발생한다.

@AllArgsConstructor
@Controller
public Class TestController {

    private TestService testService;

    @GetMapping("async")
    public String testAsync() {
        log.info("TEST ASYNC");
        try {
            for(int i=0; i<50; i++) {
                testService.asyncMethod(i);
        } catch (TaskRejectedException e) {
            // 방어코드
        }
        return "";
    }
}

답글 남기기