Callable
- 리턴값이 있음
- 예외를 던질 수 있음
Runnable
- 리턴값이 없음
- 예외를 던질 수 없음
1. RestTemplate
가정
- localhost:8081 쪽의 작업은 오래걸린다.
- 나에게 많은 요청이 온다.
아래의 코드는 block 방식이므로
- 작업시간 * 요청수 만큼의 시간이 걸림
@RestController
public static class MyController {
RestTemplate rt = new RestTemplate();
@GetMapping("/rest")
public String rest(int idx) {
String res = rt.getForObject("http://localhost:8081/service?req={req}", String.class, "hello " + idx);
return "rest " + idx;
}
}
2. AsyncRestTemplate
위의 시간이 많이걸리는 점을 AsyncRestTemplate 으로 해결
- ListenableFuture 로 리턴하면 스프링은 알아서
- 서블릿 쓰레드를 반환
- 결과값에 대한 콜백에 대한 처리를 MVC 가 처리
@RestController
public static class MyController {
AsyncRestTemplate rt = new AsyncRestTemplate();
@GetMapping("/rest")
public ListenableFuture<ResponseEntity<String>> rest(int idx) {
// 스프링은
// 비동기적으로 처리하니까 2초동안 대기하지 않음
// 결과값 처리에 대한 콜백은 스프링 MVC 가 알아서 해줌
return rt.getForEntity("http://localhost:8081/service?req={req}", String.class, "hello " + idx);
}
}
추가작업
- 추가적인 작업에 대해서는
- ListenableFuture 에 콜백을 추가
- 결과값을 DeferredResult 로 반환하며, 콜백 내에서 DeferredResult 의 결과값을 세팅하는 방식으로 추가 작업 진행
@RestController
public static class MyController {
AsyncRestTemplate rt = new AsyncRestTemplate(new Netty4ClientHttpRequestFactory(new NioEventLoopGroup(1)));
@GetMapping("/rest")
public DeferredResult<String> rest(int idx) {
DeferredResult<String> dr = new DeferredResult<>();
// 스프링은
// 비동기적으로 처리하니까 2초동안 대기하지 않음
// 결과값 처리에 대한 콜백은 스프링 MVC 가 알아서 해줌
ListenableFuture<ResponseEntity<String>> f1 = rt.getForEntity("http://localhost:8081/service?req={req}", String.class, "hello " + idx);
f1.addCallback(
s -> {
dr.setResult(s.getBody() + "/work");
},
e -> {
dr.setErrorResult(e.getMessage());
});
return dr;
}
}
중첩작업
- ListenableFuture 중첩하여 작업
@RestController
public static class MyController {
@Autowired
MyService myService;
AsyncRestTemplate rt = new AsyncRestTemplate(new Netty4ClientHttpRequestFactory(new NioEventLoopGroup(1)));
@GetMapping("/rest")
public DeferredResult<String> rest(int idx) {
DeferredResult<String> dr = new DeferredResult<>();
// 스프링은
// 비동기적으로 처리하니까 2초동안 대기하지 않음
// 결과값 처리에 대한 콜백은 스프링 MVC 가 알아서 해줌
ListenableFuture<ResponseEntity<String>> f1 = rt.getForEntity("http://localhost:8081/service?req={req}", String.class, "hello " + idx);
f1.addCallback(
s -> {
ListenableFuture<ResponseEntity<String>> f2 = rt.getForEntity("http://localhost:8081/service2?req={req}", String.class, s.getBody());
f2.addCallback(s2 -> {
ListenableFuture<String> f3 = myService.work(s2.getBody());
f3.addCallback(s3 -> {
dr.setResult(s3);
}, e3 -> {
dr.setErrorResult(e3.getMessage());
});
}, e2 -> {
dr.setErrorResult(e2.getMessage());
});
},
e -> {
dr.setErrorResult(e.getMessage());
});
return dr;
}
}
@Service
public static class MyService {
@Async
public ListenableFuture<String> work(String req) {
return new AsyncResult<>(req + "/asyncwork");
}
}
'토비의봄' 카테고리의 다른 글
8. CompletableFuture (2) | 2021.03.09 |
---|---|
7. AsyncTemplate 의 콜백헬, 중복작업 문제 (0) | 2021.03.08 |
5. 자바와 스프링의 비동기 개발기술 (0) | 2021.03.05 |
4.3. Reactive Streams (0) | 2021.03.03 |
4.2. Reactive Streams (0) | 2021.02.28 |