Я написал следующий код, чтобы проверить производительность как Synt RestTemplate, так и AsyncRestTemplate. Я просто запускал его несколько раз вручную на POSTMAN.Spring RestTemplate - async vs sync restTemplate
Мы просто проездом 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());
}
В большинстве случаев, оба метода фактически возвращают результаты с очень похожим временем, усредняя 2800 мс в обоих асинхронных и синхронных вызовах.
Я делаю что-то неправильное, поскольку я ожидал бы, что вызов асинхронного вызова будет намного быстрее?
Привет, спасибо за ваш ответ. Я действительно задаюсь вопросом, но когда мы вызываем ResponseEntity entity = future.get() в вашем коде, не блокирует ли этот код так, чтобы цикл for не продолжался до получения ответа? Я вижу незначительное улучшение во времени, когда вызов возвращается в 2500 мс или около того, но он не является существенным. –
Simon
yes, future.get() блокирует, но в этот момент все запросы уже отправлены. Если вы можете использовать JDK8 CompletableFutures или другую библиотеку композиций, у вас может быть что-то более эффективное. Измеряя это, имейте в виду, что создание RestTemplate/AsyncRestTemplate требует времени и ресурсов и должно выполняться один раз (и не должно учитываться в вашем таймере) –