我要在下面的声明中对黑体进行澄清(我提供了完整的段落仅供参考):
RestTemplate不适合在非阻塞应用程序中使用,因此Spring WebFlux应用程序应始终使用WebClient。 在大多数并发情况下,以及在构成一系列相互依赖的远程调用时,在Spring MVC中也应该首选WebClient 。
在这里找到:https://docs.spring.io/spring/docs/current/spring-framework-reference/web-reactive.html
对于Spring MVC应用程序,使用WebClient
比RestTemplate
有什么好处?与说WebClient
配置了apache RestTemplate
和HttpClient
并配置了正确的连接和套接字配置相比,PoolingHttpClientConnectionManager
如何实现更高的规模?
答案 0 :(得分:4)
WebClient
是非阻塞的,而RestTemplate
是阻塞/同步的。如果您将非阻塞WebFlux API与阻塞库一起使用,则实际上是将其转换为阻塞API。
考虑RestTemplate
实际上为每个事件创建一个新的 Thread ,而WebClient
创建一个 Task (就像在队列,这实际上是Reactor在幕后为您管理的内容)。
如果每个非阻塞任务都有一个阻塞调用来支持它,那么您很快就会饿死( Thread )(就像每个RestTemplate
一样;请注意,委派给{{1 }}仍在阻止通话)。
另一方面,任务将由反应框架进行排队,并在您拥有适当的可用资源时执行。
为什么将WebClient与Spring MVC结合使用
WebClient是非阻塞的!您可以使用所有ConnectionManager
功能(发布,订阅,反压等)。这有助于节省资源(即,您使用更少的线程和更少的内存),并且Reactor将允许您最大化使用未使用的线程。
这里的问题不是Spring MVC真正的“为什么我应该使用WebClient”,而是我的应用程序中的“为什么我应该使用反应/非阻塞”框架。互联网上有很多有关此问题及其答案的示例(here's one。
Flux
和Mono
也可以返回Java 8 CompletableFuture
。
为什么将WebClient与WebFlux一起使用
在您的referenced in that documentation页面上查看此报价:
WebClient 使用与 WebFlux 服务器应用程序相同的编解码器,并且 共享一个通用基本程序包,一些通用API和基础结构 服务器功能的Web框架。该API公开了Reactor 助焊剂 和单声道类型
关键是Flux
使用与WebClient
相同的反应式非阻塞类型。这就是为什么集成如此完美并且您获得出色的任务功能的原因。例如(并且我正在从that doc借用一小段代码):
Flux
看看这段代码如何产生WebClient client = WebClient.create("http://example.org");
Mono<Void> result = client.post()
.uri("/persons/{id}", id)
.contentType(MediaType.APPLICATION_JSON)
.body(personMono, Person.class)
.retrieve()
.bodyToMono(Void.class);
吗? Mono
是建立在上的,这是一个反应式构造,这就是为什么要在框架中使用它。例如,您实际上可以return that Mono
reactively in a Controller
call:
WebFlux
这类事情是他们说您应该在@PostMapping("/person")
Mono<Void> create(@RequestBody Publisher<Person> personStream) {
// ... above code could go here...
return result;
}
库中使用WebClient
的关键原因。
答案 1 :(得分:0)
经过一些研究,我相信答案就在于Spring的DeferredResult。要从此blog中窃取一点文字,
DeferredResult是一个可能尚未完成的计算的容器,它将在将来提供。 Spring MVC使用它来表示异步计算,并利用Servlet 3.0 AsyncContext异步请求处理。
我相信发生在WebFlux之前的事情是这样,DeferredResult概念是在Spring MVC内部支持异步IO的第一个切入点,例如,现在已经弃用的AsyncRestTemplate返回了ListenableFuture
包装器。
因此,这意味着如果我有一个相对简单的带有Spring MVC的REST API,我可能会返回一个DeferredFuture
并通过WebClient
异步生成其结果,从而获得异步的一些好处处理而不必迁移到Spring MVC(对于某些项目可能是不可行的)。