오늘은 프로젝트에서 적용한 일괄등록에서 사용한 @Async를 포스팅해볼게요.
월래는 Batch를 이용하여 새벽시간에 동작을 하도록 적용을 하였는데 @Async를 이용하여 빠르게 선처리 작업을 하고 이후 Async메서드를 호출하여 비동기 방식으로 작동하도록 구현을 하였습니다.
@Configuration
@EnableScheduling
@EnableAsync
public class AsyncThreadConfiguration {
@Bean(name = "asyncExecutor")
public Executor asyncThreadTaskExecutor() {
ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();
threadPoolTaskExecutor.setCorePoolSize(2); //최초생성수
threadPoolTaskExecutor.setMaxPoolSize(4); //max생성수
threadPoolTaskExecutor.setThreadNamePrefix("fabs-batch-pool");
return threadPoolTaskExecutor;
}
public class HandlingExecutor implements AsyncTaskExecutor {
private final AsyncTaskExecutor executor;
public HandlingExecutor(AsyncTaskExecutor executor) {
this.executor = executor;
}
@Override
public void execute(Runnable task) {
executor.execute(createWrappedRunnable(task));
}
@Override
public void execute(Runnable task, long startTimeout) {
executor.execute(createWrappedRunnable(task), startTimeout);
}
@Override
public Future<?> submit(Runnable task) {
return executor.submit(createWrappedRunnable(task));
}
@Override
public <T> Future<T> submit(final Callable<T> task) {
return executor.submit(createCallable(task));
}
private <T> Callable<T> createCallable(final Callable<T> task) {
return () -> {
try {
return task.call();
} catch (Exception ex) {
handle(ex);
throw ex;
}
};
}
private Runnable createWrappedRunnable(final Runnable task) {
return () -> {
try {
task.run();
} catch (Exception ex) {
handle(ex);
}
};
}
private void handle(Exception ex) {
log.info("Failed to execute task. : {}", ex.getMessage());
log.error("Failed to execute task. ", ex);
}
public void destroy() {
if (executor instanceof ThreadPoolTaskExecutor) {
((ThreadPoolTaskExecutor) executor).shutdown();
}
}
}
먼저 ThreadPool설정입니다.
setCorePoolSize 최초 생성 시 사용되는 Thread 수입니다.
setMaxPoolSize 생성할 수 있는 Thread Max값입니다.
setThreadNamePrefix ThreadPool이 여러 곳에서 사용이 되면 알아볼 수 있도록 Name을 지정합니다.
@Bean(name = "asyncExecutor") <- "asyncExecutor"이름으로 비동기 호출을 사용할 수 있습니다.
//Controller Class
@RequestMapping(value = "/excelUpload", method = RequestMethod.POST)
public ResponseEntity<HttpResponse<?>> excelUpload(MultipartHttpServletRequest req, HttpServletResponse res,
@AuthenticationPrincipal UserAuthentication userAuthentication) throws Exception {
//비동기 Method호출
Service.add(reqFundManagement);
//비동기 Method 실행이 다 완료 안되더라도 이후 코드 실행
}
//Service Class
@Async("asyncExecutor")
public void add(ReqFundManagement reqFundManagement) {
// 필요한 소스구현
}
기존 방식은
1) Excel업로드
2) 대상자 추출(LIST)
3) 대상자 등록
4) 대상자 API를 이용해 데이터 가져오기
대상자가 많을수록 3->4번이 대기 시간들이 길어져서 Batch로 만들려고 고민 중에 비동기 호출 방식 확인
비동기
1) Excel업로드
2) 대상자 추출(LIST)
3) 대상자 등록
4) 대상자 API를 이용해 데이터 가져오기
호출 순서는 같은데 3->4번 실행 후 4번 응답 대기 없이 바로 3->4가 반복을 하여 3번 대상자 먼저 등록이 되고 4번은 비동기로 작동이 돼서 여러 건을 동시에 가져와서 호출 시간이 절약이 되었어요.
'개발 > Java' 카테고리의 다른 글
Java Excel Upload (0) | 2021.02.25 |
---|---|
이클립스 Formatter off (0) | 2021.02.16 |
Java 단방향,양방향 암호화 (1) | 2021.01.25 |
Spring RestTemplate Converter오류 (0) | 2021.01.14 |
List 중복 제거 및 List 정렬(Collections.sort) (1) | 2021.01.04 |