클라이언트 요청에 비동기 처리를 지원하는 SpringBoot @Async 사용법
기본적으로 Config에 @EnableAsync 어노테이션으로 Async사용을 활성화 시키고
비동기 처리가 필요한 서비스 메소드에 @Async 어노테이션을 작성하면 사용 가능하다.
@EnableAsync 애노테이션을 사용하면 기본 SimpleAsyncTaskExecutor를 사용하여 매번 쓰레드를 생성하는 방식이다.
쓰레드풀을 적용해서 처리를 할 경우 ThreadPoolTaskExecutor를 빈으로 등록해준다.
@Bean("myExecutor") 빈네임 설정을 통해 @Async("myExecutor") 어노테이션 사용시 풀을 지정할 수도 있다.
SpringBoot2.0 이상이면 application.yaml 파일로도 설정이 가능하다.
spring:
task:
execution:
pool:
core-size: 5
max-size: 5
queue-capacity: 10
- core-size: 동시에 실행 시킬 스레드 개수
- max-size: 스레드 풀의 최대 사이즈
- queue-capacity: core-size 개수를 넘어서는 task가 왔을 때 queue에 대기 시킬 task 개수
* 동작방식
요청이 들어오면 core-size 만큼의 스레드를 생성해서 동시 실행 시키고, 작업이 계속 실행중에 그 이상의 요청이 들어올 경우 먼저 queue에 queue-capacity 개수 만큼의 요청을 대기 시킨다. 그리고 queue-capacity 개수 이상이 넘어가는 요청이 계속 들어올 경우 그때 max-size 개수 만큼 스레드 생성해서 처리 진행
(core-size -> queue-capacity만큼 대기 -> max-size 스레드 생성)
이제 Service에서 아래와 같이 @Async 를 적용한 메소드를 선언하고 Controller에서 호출 테스트를 한다.
@Service
public class AsyncService {
private static final Logger logger = LoggerFactory.getLogger(AsyncService.class);
@Async
public void onAsync() throws Exception{
Thread.sleep(5000);
logger.info("Called Async");
}
}
@RestController
public class AsyncController {
@Autowired
private AsyncService asyncService;
@GetMapping({"/", "/async"})
public String async(Model model) throws Exception{
asyncService.onAsync();
return "done";
}
}
리턴이 필요한 비동기 처리 샘플은 아래와 같다
// Service
@Async
public CompletableFuture<String> returnOnAsync() throws Exception{
Thread.sleep(5000);
logger.info("Called Async");
return new AsyncResult<>("Called Async").completable();
}
// Controller
@GetMapping({"/", "/async_return"})
public String async_return(Model model) throws Exception{
CompletableFuture<String> future = asyncService.returnOnAsync();
logger.info("pass 1!!");
future.thenAccept(p -> logger.info("future : {}", p));
logger.info("pass 2!!");
return "done";
}
테스트 결과 로그는 아래와 같이 찍힌다.
제약 사항
@Async의 제약사항은 @Transactional과 동일하게 기본적으로 Proxy방식으로 동작하여
- public method만 @Async가 가능하다. private는 불가능
- self-invocation(자가 호출)에서는 불가 => 같은 클래스 내부의 메서드를 호출하는 것은 안됨
'개발 > SpringBoot' 카테고리의 다른 글
java 어플리케이션 실행 시 JVM args(JAVA_OPTS) 적용 (0) | 2021.12.08 |
---|---|
SpringBoot Jsaypt 사용 application.yml 암호화 (0) | 2021.12.03 |
SpringBoot jar를 타 프로젝트에 Dependency 라이브러리로 추가 (0) | 2021.12.03 |
SonarQube 설치 및 구성 (0) | 2021.11.30 |
SpringBoot Scouter APM 구성 (0) | 2021.11.30 |
댓글