Spring 用于同步请求的 RestTemplate 与 WebClient
Spring RestTemplate vs WebClient for sync requests
抱歉,如果之前有人问过这个问题,但我没有找到匹配的问题。
我有一个应用程序可以对其他服务执行 api 调用。我正在考虑使用 WebClient 而不是 RestTemplate,正如 Spring 所建议的那样。我正在执行专门的同步调用。我知道 WebClient 在设计时考虑了反应式方法,但理论上仅将 WebClient 用于阻止调用是否可以?我担心每次调用都必须调用 .block()
才能获取数据。所以我的问题是:
- 使用
.block()
的安全性如何?通常可以在 WebClient 中阻塞线程吗?
- 使用 WebClient 阻止调用背后的机制是否类似于 RestTemplate 所做的?
- 是否有可能性能会比我只使用 RestTemplate 时更差?
提前致谢!
在我们的应用程序中,我们从 RestTemplate 迁移到 WebClient 没有任何问题,.block() 工作正常
Response response = this.webClient
.post()
.uri(uri)
.body(fromValue)
.retrieve()
.bodyToMono(Response.class)
.timeout(Duration.ofMillis(timeoutMillis))
.block();
这和 RestTemplate 做的一样,它以同步的方式发送请求,我们已经在 PROD 中工作了几个月没有任何问题
回答您的问题:
- 请不要那样做。通过这样做,您将 Spring Webflux 的所有好处都扔进了垃圾桶。您正在复制 non-reactive 堆栈行为。
- 实际上是的。线程将被阻塞,等待您调用的服务的响应。
- 我会说它会很相似,但如果没有任何好处,您的代码将更难阅读。
底线是:为了充分利用 Spring Webflux 的反应堆栈,您需要有一个完全反应的代码库。即使是基础设施也必须支持反应行为,最简单的例子就是数据库。
此外,您混淆了异步行为和反应行为。 Spring Webflux 本质上是反应性的,这给 table 带来了其他好处(看看 https://www.baeldung.com/spring-mvc-async-vs-webflux)。
既然好像有什么误解,我会尽力回答问题。
How safe is it to use .block() and is it ok in general to block threads in WebClient?
阻塞总是安全,但天气与否影响性能是另一回事。当一个请求进来时,它会被分配一个线程。当我们使用 RestTemplate
发出请求时,同一个线程将执行外部请求,而 RestTemplate
将在后台阻塞该线程以等待响应。
这绝不是线程的高效使用,但它是完全安全的,这就是过去 20 年来大多数 Web 服务器的工作方式。
当在 non-reactive 应用程序中使用 WebClient
并且您阻塞了 Mono<T>
(您实际上会这样做)时,框架将首先检查该线程是否是一种线程你被允许阻塞(不是 nio-thread),然后它使用 CountDownLatch
pauses/blocks 调用线程 CountDownLatch#await
直到第一个 onNext/onComplete/onError 信号到达。这在阻塞应用程序中完全没问题。可以找到相关代码here.
当您将 WebClient
添加到 class 路径时,您将自动获得 netty 作为底层服务器,这可能是个好消息。如果你想改变它,那么你需要明确说明。
此外,建议如果您执行多个请求,那么在诉诸 block
之前,您应该尽可能多地链接响应式调用。
如果您想转移到反应式应用程序,那么这是一种慢慢转移应用程序的好方法,慢慢地做越来越多的反应性事情,然后调用 block
到 return到常规世界。
你完全反应了吗?不,你是不是像以前一样是一个阻塞的网络服务器,是的。 RestTemplate
很可能不会更糟吗?从维护的角度来看,您是否比以前更好,是的,因为 spring 已经正式退出,不会再对 RestTemplate
.
进行任何更新
Is the mechanics behind blocking calls with WebClient similar to what RestTemplate does?
嗯,这很难说,因为 RestTemplate
主要只是底层服务器实现提供的 HttpClient
的包装。
阻塞的编写方式可能不同,但它们最终所做的很可能是相同的。 A Mono<T>
使用 CountDownLatch
重复调用 getCount
块,然后在块之间调用闩锁 await
直到响应返回。我没有查看 RestTemplate
包装的不同 HttpClients,您需要仔细阅读它们中的每一个(tomcat、jetty、undertow 等)
Is there a possibility that the performance would be worse than in case I just use RestTemplate?
这非常很难说,因为性能不是非黑即白的。这完全取决于硬件、要完成的工作类型、代码的编写方式、线程池大小、操作系统等。
Netty
是一个完全事件驱动的服务器,它开始成为 事实上的 网络服务器标准 Java 社区。 Undertow decided to switch out their entire core to the netty core
,因为它太好了,而且更容易维护。
由于 Netty
是事件驱动的,运行将它作为一个 旧 服务器,每个请求一个线程可能会损害性能,因为它没有针对那种类型的工作,但另一方面,当你 运行 它完全由事件驱动时,它会发光。
回答这个问题的唯一方法是做自己的基准测试,我们无法为您回答。
如果您想了解更多关于 netty 的实际工作原理,建议您阅读 Netty in Action 这本书,这本书不是免费的,但非常适合阅读以了解 Netty
及其 async
线程模型。
抱歉,如果之前有人问过这个问题,但我没有找到匹配的问题。
我有一个应用程序可以对其他服务执行 api 调用。我正在考虑使用 WebClient 而不是 RestTemplate,正如 Spring 所建议的那样。我正在执行专门的同步调用。我知道 WebClient 在设计时考虑了反应式方法,但理论上仅将 WebClient 用于阻止调用是否可以?我担心每次调用都必须调用 .block()
才能获取数据。所以我的问题是:
- 使用
.block()
的安全性如何?通常可以在 WebClient 中阻塞线程吗? - 使用 WebClient 阻止调用背后的机制是否类似于 RestTemplate 所做的?
- 是否有可能性能会比我只使用 RestTemplate 时更差?
提前致谢!
在我们的应用程序中,我们从 RestTemplate 迁移到 WebClient 没有任何问题,.block() 工作正常
Response response = this.webClient
.post()
.uri(uri)
.body(fromValue)
.retrieve()
.bodyToMono(Response.class)
.timeout(Duration.ofMillis(timeoutMillis))
.block();
这和 RestTemplate 做的一样,它以同步的方式发送请求,我们已经在 PROD 中工作了几个月没有任何问题
回答您的问题:
- 请不要那样做。通过这样做,您将 Spring Webflux 的所有好处都扔进了垃圾桶。您正在复制 non-reactive 堆栈行为。
- 实际上是的。线程将被阻塞,等待您调用的服务的响应。
- 我会说它会很相似,但如果没有任何好处,您的代码将更难阅读。
底线是:为了充分利用 Spring Webflux 的反应堆栈,您需要有一个完全反应的代码库。即使是基础设施也必须支持反应行为,最简单的例子就是数据库。
此外,您混淆了异步行为和反应行为。 Spring Webflux 本质上是反应性的,这给 table 带来了其他好处(看看 https://www.baeldung.com/spring-mvc-async-vs-webflux)。
既然好像有什么误解,我会尽力回答问题。
How safe is it to use .block() and is it ok in general to block threads in WebClient?
阻塞总是安全,但天气与否影响性能是另一回事。当一个请求进来时,它会被分配一个线程。当我们使用 RestTemplate
发出请求时,同一个线程将执行外部请求,而 RestTemplate
将在后台阻塞该线程以等待响应。
这绝不是线程的高效使用,但它是完全安全的,这就是过去 20 年来大多数 Web 服务器的工作方式。
当在 non-reactive 应用程序中使用 WebClient
并且您阻塞了 Mono<T>
(您实际上会这样做)时,框架将首先检查该线程是否是一种线程你被允许阻塞(不是 nio-thread),然后它使用 CountDownLatch
pauses/blocks 调用线程 CountDownLatch#await
直到第一个 onNext/onComplete/onError 信号到达。这在阻塞应用程序中完全没问题。可以找到相关代码here.
当您将 WebClient
添加到 class 路径时,您将自动获得 netty 作为底层服务器,这可能是个好消息。如果你想改变它,那么你需要明确说明。
此外,建议如果您执行多个请求,那么在诉诸 block
之前,您应该尽可能多地链接响应式调用。
如果您想转移到反应式应用程序,那么这是一种慢慢转移应用程序的好方法,慢慢地做越来越多的反应性事情,然后调用 block
到 return到常规世界。
你完全反应了吗?不,你是不是像以前一样是一个阻塞的网络服务器,是的。 RestTemplate
很可能不会更糟吗?从维护的角度来看,您是否比以前更好,是的,因为 spring 已经正式退出,不会再对 RestTemplate
.
Is the mechanics behind blocking calls with WebClient similar to what RestTemplate does?
嗯,这很难说,因为 RestTemplate
主要只是底层服务器实现提供的 HttpClient
的包装。
阻塞的编写方式可能不同,但它们最终所做的很可能是相同的。 A Mono<T>
使用 CountDownLatch
重复调用 getCount
块,然后在块之间调用闩锁 await
直到响应返回。我没有查看 RestTemplate
包装的不同 HttpClients,您需要仔细阅读它们中的每一个(tomcat、jetty、undertow 等)
Is there a possibility that the performance would be worse than in case I just use RestTemplate?
这非常很难说,因为性能不是非黑即白的。这完全取决于硬件、要完成的工作类型、代码的编写方式、线程池大小、操作系统等。
Netty
是一个完全事件驱动的服务器,它开始成为 事实上的 网络服务器标准 Java 社区。 Undertow decided to switch out their entire core to the netty core
,因为它太好了,而且更容易维护。
由于 Netty
是事件驱动的,运行将它作为一个 旧 服务器,每个请求一个线程可能会损害性能,因为它没有针对那种类型的工作,但另一方面,当你 运行 它完全由事件驱动时,它会发光。
回答这个问题的唯一方法是做自己的基准测试,我们无法为您回答。
如果您想了解更多关于 netty 的实际工作原理,建议您阅读 Netty in Action 这本书,这本书不是免费的,但非常适合阅读以了解 Netty
及其 async
线程模型。