Spring RestTemplate 与 WebClient 的同步请求

tra*_*_13 4 java spring resttemplate spring-webflux spring-webclient

抱歉,如果之前有人问过这个问题,但我没有找到匹配的问题。

我有一个对其他服务执行 api 调用的应用程序。我正在考虑按照 Spring 的建议使用WebClientover 。RestTemplate我只执行同步 HTTP 调用。

我知道WebClient设计时考虑了响应式方法,但从理论上讲:可以WebClient仅用于阻止调用吗?我担心的是我必须.block()每次通话才能获取数据。所以我的问题是:

  1. 使用它的安全性如何.block()?通常可以阻止其中的线程吗WebClient
  2. 阻止调用背后的机制是否与WebClient类似RestTemplate
  3. 性能是否有可能比我只使用时更差RestTemplate

提前致谢!

Tho*_*olf 12

由于似乎存在误解,我将尽我所知尽力回答这些问题。

使用它的安全性如何.block()?通常可以阻止其中的线程吗WebClient

阻塞总是安全的,但是否影响性能则是另一回事。当请求到来时,它会被分配一个线程。RestTemplate当我们使用同一线程发出请求时,将执行外部请求,并RestTemplate会在后台阻塞该线程以等待响应。

这绝不是线程的有效使用,但它是完全安全的,这就是过去 20 年来大多数 Web 服务器的工作方式。

WebClient当在响应式应用程序中使用并且您阻止Mono<T>(您本质上将会这样做)时,框架将首先检查该线程是否是允许您阻止的线程类型(不是 nio -thread),然后它使用 aCountDownLatch暂停/阻塞调用线程,CountDownLatch#await直到第一个onNext/onComplete/onError信号到达。这在阻塞应用程序中完全没问题。您可以在这里找到相关代码。

当您添加WebClient到类路径时,您将自动将 netty 作为底层服务器,了解这一点可能会很有帮助。如果你想改变这一点,那么你需要明确这一点。

另外,建议如果您执行多个请求,那么在诉诸block.

如果您想转移到响应式应用程序,那么这是缓慢转移应用程序的一种非常好的方法,方法是慢慢地执行越来越多的响应式操作,然后调用block返回到常规世界。

你完全有反应吗?不,您是否像以前一样阻塞网络服务器,是的。是不是更糟,RestTemplate很可能不是。从维护的角度来看,你比以前更好了吗?是的,因为 spring 已经正式退出,不会再有任何更新了RestTemplate

阻止调用背后的机制是否与WebClient类似RestTemplate

嗯,这很难说,因为主要只是底层服务器实现提供的RestTemplate包装。HttpClient

阻塞的编写方式可能不同,但它们最终的作用很可能是相同的。AMono<T>块使用 aCountDownLatch重复调用getCount,然后在块之间调用锁存器,await直到响应返回。我没有看过HttpClient正在包装的不同的s RestTemplate,你需要阅读它们中的每一个(tomcat,jetty,undertow,等等)

性能是否有可能比我只使用时更差RestTemplate

很难说,因为性能不是黑白分明的。这一切都取决于硬件、要完成什么类型​​的作业、代码是如何编写的、线程池大小、操作系统等。

Netty是一个完全事件驱动的服务器,它开始成为Java 社区中 Web 服务器的事实标准。Undertow 决定将他们的整个核心切换到netty core,因为它非常好,而且更易于维护。

Netty与事件驱动一样,将其作为每个请求一个线程的服务器运行可能会损害性能,因为它没有针对该类型的工作进行优化,但另一方面,当您完全事件驱动地运行它时,它会表现出色。

回答这个问题的唯一方法是做你自己的基准测试,我们无法为你回答这个问题。

如果你想更多地了解 Netty 的实际工作原理,建议阅读《Netty in Action》一书,该书不是免费的,但非常适合理解其内部工作原理Netty及其async线程模型。