본문 바로가기

Programming/SpringFramework

스프링 async 비동기처리

스프링 에서 비동기(Async) 사용


일반적으로 사용하는 다음과 같은 컨트롤러 코드는 동기화를 기본으로한다.


@RestController
@RequestMapping("/accounts")
public class AccountController {
private Logger log = LoggerFactory.getLogger(this.getClass());
@Autowired
AccountService accountService;
@RequestMapping(value ="/", method = RequestMethod.GET)
public String test(){
return "testgoood";
}



 하지만 이와 같이 동기화를 하면 어떠한 api에 많은 Request가 들어오거나, 메일서비스같이 오래걸리는 api라면 스레드대기상태가 걸린다.

스레드를 할당 받지 못하는경우도 생길 수 있다.  


 그렇다면 어떻게 해야하는가!!

 해결법 비동기!


 비동기란 일반적으로 어떠한 처리를 동기화 하지않고 동시에 여러곳에서 처리하는 것을 말하는데 일반적으로 다음과 같이 움직인다.

- 어떠한 요청이 있을때 바로 리턴값을 받는데 이것을 결과 값이 아니다. 모든 처리가 끝난 후 결과값을 간접적으로 받는다.

- 요청별로 별도의 스레드를 통해 처리한다.



 약간 요런느낌??

그리고...

스프링 3.2 부터 비동기를 지원하는 라이브러리가 등장했다.


1.Callable

 요청 받은 스레드를 서블릿 컨테이너에 반환하고 스프링에서 제공하는 TaskExcutor의 새로운 스레드를 생성하여 처리한다. 그 동안 원래 스레드는 새로운 요청을 처리할 수 있게 된다. 그리고 분리된 스레드 안에서 Callable클래스를 호출하여 그 리턴 값과 원래 요청된 응답을 서블릿 컨테이너로 보낸다.


- 리턴 타입에 다음과 같이 Callable을 추가만 하면 된다.


@EnableWebMvc
public class AsyncConfig extends WebMvcConfigurerAdapter {
@Override
public void configureAsyncSupport(AsyncSupportConfigurer configurer) {
// TODO Auto-generated method stub
ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
taskExecutor.setCorePoolSize(10);
taskExecutor.setMaxPoolSize(20);
taskExecutor.setQueueCapacity(50);
configurer.setTaskExecutor(taskExecutor);
}
}
view raw async 설정 hosted with ❤ by GitHub

<스레드풀 생성>


@RestController
@RequestMapping("/accounts")
public class AccountController {
private Logger log = LoggerFactory.getLogger(this.getClass());
@Autowired
AccountService accountService;
@RequestMapping(value ="/{email}", method = RequestMethod.GET)
public @ResponseBody Callable<Account> findByEmail(@ModelAttribute Account account){
return () -> {
return accountService.findByEmail(account.getEmail());
};
}

<컨트롤러 적용>


2.DeferredResult

 컨트롤러의 리턴을 별도의 작업에서 할 수 있게 해준다. 하지만 이스레드는 스프링에의해 관리 되는 것이 아니다.

 DeferredResult클래스는 어떤 요청에 대한 응답을 이벤트를 Queue에 저장하고 있다가 DeferredResult.setResult() 메소드가 호출되면 DispatcherSerlvet으로 응답을 보낸다.  즉 서버가 Push하는 기술들을 구현할 수 있게 해준다.


참고 : 3.Asynchronous Support in Spritng MVC 3.2