Spring RestTemplate - async vs sync restTemplate

2022-09-02 05:37:25

我编写了以下代码来测试同步 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 - 异步,以 2794 毫秒为单位返回:

//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 毫秒。

我是否做了一些不正确的事情,因为我本来以为异步调用会快得多?


答案 1

如今,赞成.所以没有人应该再使用那个类了!AsyncRestTemplate@DeprecatedWebClient

https://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/reactive/function/client/WebClient.html


答案 2

我想说的是,你在这里错过了AsyncRest的真正好处。您应该向要发送的每个请求添加回调,以便响应仅在可用时才会被处理。

实际上,a 的方法返回 一个,您可以将回调任务连接到该任务。请参阅官方文档ListenableFuture以获取更多信息。getForEntityAsyncRestTemplateListenableFuture

例如,在您的情况下,它可能是:

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());
            }
        });
}

推荐