스프링에는 비동기 구현체가 여러가지 있는데
Controller 단에서 간단하게 비동기 요청을 처리할 수 있는 @Callable을 알아보고자 합니다.
@Callable ?
Spring MVC 3.2부터 추가된 Servlet 3을 기반으로한 비동기 요청 프로세스
- 요청 프로세스 답게 내부(Service단)를 비동기화 시켜주진 않습니다.
Callable의 특징
- Thread가 Spring MVC 내에서 관리된다.(내부 TaskExecutor)
- Controller의 RequestMapping method에서 Callable 객체를 감싸서 리턴한다.
Callable의 동작 방식
- 컨트롤러에 요청이 들어오면 값을 반환하는 대신 Callable 을 먼저 반환한다.
- Spring MVC는 내부 TaskExecutor에게 해당 작업을 전달한다. (별도의 독립된 Thread)
- Servlet Container Thread는 해당 요청(작업)에서 벗어나 다른 요청을 받을 수 있게된다.
- 작업이 완료되면 Callable은 결과를 생성하고, Spring MVC는 Servlet Container에게 재요청을 진행한다.
- DispatcherServlet은 Callable에게서 객체를 반환받아 작업을 진행한다.
Callable 사용 방법
Controller Method의 반환값을 Callable로 감싸서 반환하면 됩니다.
@GetMapping(value = "/async")
public Callable<String> async() {
log.info("request async");
return () -> { // 별도의 TaskExecutor 내에서 실행
Thread.sleep(5000); // 지연 5초
return "OK";
};
}
비동기 Test
간단하게 GET요청을 어떻게 처리하는지 비교하겠습니다.
application.yml
Thread의 최대 개수를 1개로 지정해줍니다.
server:
tomcat:
threads:
max: 1
NOT Callable
요청을 보내고 지연을 5초 설정해줍니다.
@GetMapping(value = "/sync")
public String sync() {
try {
log.info("request sync");
Thread.sleep(5000); //지연 5초
log.info("response sync");
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
return "OK";
}
/sync 로 요청을 3번 보내면
이렇게 한번에 하나의 요청밖에 처리를 못합니다. 다음 요청을 보내려면 5초동안 기다려야 합니다.
Callable
마찬가지로 지연 5초 설정해줍니다.
@GetMapping(value = "/async")
public Callable<String> async() {
log.info("request async");
return () -> {
Thread.sleep(5000); //지연 5초
log.info("response async");
return "OK";
};
}
/async 로 요청을 3번 보내면
요청은 보내는 즉시 처리 됩니다. 다수의 요청을 비동기로 처리할 수 있습니다.
Response 로그 MvcAsync -> Spring MVC 내부에서 처리 한다는 것을 알 수 있습니다.
'Spring' 카테고리의 다른 글
[Spring] Error : Spring Batch Jackson2 ExecutionContext Serializer (실행 컨텍스트를 직렬화/역직렬화할 수 없음) (0) | 2023.09.12 |
---|---|
[Spring] WebClient 적용기 (2) | 2023.02.27 |
[Spring] Multipartfile, Json 동시에 전송하는 방법 2가지 (3) | 2022.09.11 |
[Spring] Junit4, Junit5 Test코드의 차이(Trouble Shooting) (1) | 2022.06.17 |
[Spring] Spring Boot 기본 MVC Pattern (0) | 2022.05.23 |