使用Resttemplate多个异步HTTP请求

问题描述 投票:1回答:2

我有一个使用弹簧RestTemplate调出到多个URL的服务。

为了提高性能,我想并行执行这些请求。可我有两个选项:

  • 的java 8个利用并行流的fork-join公共池
  • completable未来使用分离的线程池

只是想知道,如果它的最佳实践与阻塞I / O调用使用并行流?

java java-8 resttemplate spring-web
2个回答
2
投票

一个ForkJoinPool是不理想的做IO的工作,因为你没有获得任何的工作特性窃取的好处。如果您计划使用您的应用程序的commonPool等部位做得比,你可能会干扰他们。一个专门的线程池,例如ExecutorService,可能是这两个之间的更好的解决方案。

我想建议的东西,甚至更好。而是自己写所有的异步封装代码的,可以考虑使用Spring的AsyncRestTemplate。它包含在Spring的Web库及其API几乎是相同的RestTemplate

Spring的核心类异步客户端的HTTP访问。公开类似的方法为RestTemplate,但回报ListenableFuture包装,而不是具体的结果。

[...]

注意:默认情况下AsyncRestTemplate依赖于标准的JDK设施,以建立HTTP连接。可以切换通过使用构造受理AsyncClientHttpRequestFactory使用例如Apache HttpComponents,Netty的,和OkHttp不同的HTTP库等。

ListenableFuture实例可以很容易地转换通过CompletableFutureListenableFuture::completable()实例。

如同在Javadoc中指出的那样,你可以控制你想通过指定AsyncClientHttpRequestFactory使用什么异步机制。有许多内置的实现,对每一所列出的库。在内部,一些图书馆可能会做你的建议,并运行在专用线程池阻塞IO。其他人,如Netty的(如果没有记错),使用非阻塞IO来运行连接。你可能会获得来自一些好处。

然后就看你如何减少的结果。随着CompletableFuture,您可以访问anyOfallOf佣工和任何的组合实例方法。

例如,

URI exampleURI = URI.create("https://www.stackoverflow.com");

AsyncRestTemplate template = new AsyncRestTemplate/* specific request factory*/();
var future1 = template.exchange(exampleURI, HttpMethod.GET, null, String.class).completable();
var future2 = template.exchange(exampleURI, HttpMethod.GET, null, String.class).completable();
var future3 = template.exchange(exampleURI, HttpMethod.GET, null, String.class).completable();

CompletableFuture.allOf(future1, future2, future3).thenRun(() -> {
    // you're done
});

AsyncRestTemplate已经被弃用,取而代之的Spring Web流量” WebClient的。这个API是相当不同的,所以我不会去到它(只是说,它确实让你得到一个CompletableFuture为好)。


2
投票

Completable未来将是一个更好的方式来做到这一点,因为它在语义上更相关的任务,你可能会保持代码的流动,同时任务收益将。

如果你使用流,与异常中处理,事实上,它是不那么相关的任务,语义在管道lambda表达式的尴尬旁边,你将不得不等待它们全部完成,即使它们是存在的在平行下。为了避免这种情况,你需要期货,但随后你会回来的第一个解决方案。

你可能会考虑混合,使用流来创建期货。但考虑到它是一个阻塞IO组请求,你很可能将没有足够的请求或时间采取并行流的优势,图书馆可能不会分裂并行的任务给你,你将是一个循环更好。

© www.soinside.com 2019 - 2024. All rights reserved.