[SPRING] 봄 RestTemplate - 비동기 대 sync restTemplate
SPRING봄 RestTemplate - 비동기 대 sync restTemplate
RestTemplate과 AsyncRestTemplate 동기화 성능을 테스트하기 위해 다음 코드를 작성했습니다. POSTMAN에서 수 차례 수동으로 실행했습니다.
우리는 10 개의 참조를 GET 호출로 전달하기 때문에 10 개의 링크를 반환 할 수 있습니다.
RestTemplate - 동기식 및 2806ms의 반환 :
ArrayList<String> references = new ArrayList<>();
ArrayList<String> links = new ArrayList<>();
RestTemplate restTemplate = new RestTemplate();
restTemplate.getMessageConverters().add(new StringHttpMessageConverter());
for (int i = 0; i < 10; i++) {
ResponseEntity<String> resource = restTemplate.getForEntity(references.get(i), String.class);
links.add(resource.getBody().toString());
}
RestTemplate - 2794ms에서 비동기 및 리턴 :
//Creating a synchronizedList so that when the async resttemplate returns, there will be no concurrency issues
List<String> links = Collections.synchronizedList(new ArrayList<String>());
//CustomClientHttpRequestFactory just extends SimpleClientHttpRequestFactory but disables automatic redirects in SimpleClientHttpRequestFactory
CustomClientHttpRequestFactory customClientHttpRequestFactory = new CustomClientHttpRequestFactory();
//Setting the ThreadPoolTaskExecutor for the Async calls
org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor pool = new org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor();
pool.setCorePoolSize(5);
pool.setMaxPoolSize(10);
pool.setWaitForTasksToCompleteOnShutdown(true);
pool.initialize();
//Setting the TaskExecutor to the ThreadPoolTaskExecutor
customClientHttpRequestFactory.setTaskExecutor(pool);
ArrayList<String> references = new ArrayList<>();
ArrayList<String> links = new ArrayList<>();
AsyncRestTemplate asyncRestTemplate = new AsyncRestTemplate(customClientHttpRequestFactory);
restTemplate.getMessageConverters().add(new StringHttpMessageConverter());
for (int i = 0; i < 10; i++) {
Future<ResponseEntity<String>> resource = asyncRestTemplate.getForEntity(references.get(i), String.class);
ResponseEntity<String> entity = resource.get(); //this should start up 10 threads to get the links asynchronously
links.add(entity.getBody().toString());
}
대부분의 경우 두 가지 방법 모두 실제로 비동기 및 동기화 호출에서 평균 2800ms의 결과를 반환합니다.
비동기 호출이 훨씬 더 빠를 것으로 예상했기 때문에 잘못된 것을하고 있습니까?
해결법
-
==============================
1.나는 여기서 AsyncRest의 진정한 이점을 놓치고 있다고 말할 것이다. 전송중인 각 요청에 콜백을 추가하여 응답이 가능한 경우에만 처리되도록해야합니다.
나는 여기서 AsyncRest의 진정한 이점을 놓치고 있다고 말할 것이다. 전송중인 각 요청에 콜백을 추가하여 응답이 가능한 경우에만 처리되도록해야합니다.
실제로 AsyncRestTemplate의 getForEntity 메서드는 콜백 작업에 연결할 수있는 ListenableFuture를 반환합니다. 더 자세한 정보는 공식 문서 ListenableFuture를보십시오.
예를 들어 귀하의 경우 :
for (int i = 0; i < 10; i++) { ListenableFuture<ResponseEntity<String>> response = asyncRestTemplate.getForEntity(references.get(i), String.class); response.addCallback(new ListenableFutureCallback<ResponseEntity<String>>() { @Override public void onSuccess(ResponseEntity<String> result) { // Do stuff onSuccess links.add(result.getBody().toString()); } @Override public void onFailure(Throwable ex) { log.warn("Error detected while submitting a REST request. Exception was {}", ex.getMessage()); } }); }
-
==============================
2.Java Future의 까다로운 점은 구성 할 수 없으며 차단하기가 쉽다는 점입니다.
Java Future의 까다로운 점은 구성 할 수 없으며 차단하기가 쉽다는 점입니다.
이 경우, future.get ()을 호출하면 코드 블록이 작성되고 응답이 돌아올 때까지 대기합니다. 사실,이 접근 방식은 순차적 호출을 만들고이 RestTemplate 구현의 비동기 특성을 활용하지 않습니다.
이 문제를 해결하는 가장 간단한 방법은 두 개의 루프로 분리하는 것입니다.
ArrayList<Future<ResponseEntity<String>>> futures = new ArrayList<>(); for (String url : references.get()) { futures.add(asyncRestTemplate.getForEntity(url, String.class)); //start up to 10 requests in parallel, depending on your pool } for (Future<ResponseEntity<String>> future : futures) { ResponseEntity<String> entity = future.get(); // blocking on the first request links.add(entity.getBody().toString()); }
분명히 JDK8 스트림, lambdas 및 ListenableFuture / CompletableFuture 또는 컴포지션 라이브러리를 사용하는 경우 더욱 세련된 솔루션이 있습니다.
from https://stackoverflow.com/questions/31572475/spring-resttemplate-async-vs-sync-resttemplate by cc-by-sa and MIT license
'SPRING' 카테고리의 다른 글
[SPRING] @Column insertable, updatable은 Spring JPA와 잘 어울리지 않습니까? (0) | 2019.02.22 |
---|---|
[SPRING] Spring-Data-Elasticsearch 설정 : Spring은 설정 파일을 찾을 수 없습니까? (0) | 2019.02.22 |
[SPRING] 감사 추적 테이블을 만들기 위해 최대 절전 모드 인터셉터를 사용하여 db에서 페치하지 않고 previouseState를 얻는 방법? (0) | 2019.02.22 |
[SPRING] 스프링 배치 프로세서 (0) | 2019.02.22 |
[SPRING] 통합 jsf, 봄, 최대 절전 모드. 스프링 빈을 JSF 관리 빈에 삽입하는 방법은 무엇입니까? (0) | 2019.02.22 |