繁体   English   中英

Spring boot WebClient 真的是异步的吗?

[英]Is Spring boot WebClient real asynchronous?

WebClient 是一个响应式客户端,它提供了 RestTemplate 的替代方案。 据说是异步的。

但我怀疑以下代码:

 WebClient.create()
            .method(HttpMethod.GET)
            .uri("http://localhost:8080/testApi")
            .retrieve()
            .bodyToMono(String.class)

它什么都不做。 没有发送任何 http 请求。 好像没有触发。 除非我通过添加.block()触发它。 但它使事情不是“异步”。

另外,我所知道的是使用.subscribe()使事情看起来异步。

但是 WebClient 是为此设计的吗? 使用 WebClient 的最佳实践是什么?

WebClient是一个反应式客户端,它提供了RestTemplate的替代方案。 据说它是异步的。

但是我对下面的代码表示怀疑:

 WebClient.create()
            .method(HttpMethod.GET)
            .uri("http://localhost:8080/testApi")
            .retrieve()
            .bodyToMono(String.class)

它什么也没做。 没有发送任何http请求。 似乎没有触发。 除非我通过添加.block()触发它。 但是它使事情不是“异步”。

另外,我所知道的是使用.subscribe()使事情看起来异步。

但是,WebClient是为此目的设计的吗? 使用WebClient的最佳实践是什么?

是的,但混乱是可以理解的。 你会从响应式社区的一个不太具有建设性的部分中获得一些阴影,用于像你所做的那样构建问题,但是作为一个在 NodeJS 工作后开始使用响应式的人,它与它的核心是异步的(并且在此之前做了一些 Twisted ) 反应式接口有点笨拙,文档通常写得不好(但越来越好),默认值通常会让你大吃一惊。

一些入门提示,没有特定的顺序:

  • 归根结底,它只是 Netty 的一个包装器,它是一个非常可靠、维护良好、文档齐全、非常好的库。 在负载测试期间的某个时候,您可能会看到引用 Netty 等的奇怪队列异常,阅读它可能不会有什么坏处: https : //netty.io/ 旁注:spring 经常这样做 - 用一堆令人困惑的新术语和笨重的、迅速弃用的接口包装了在其他地方开发的可靠技术

  • 跳过有关背压等的大多数咆哮,并拿起 Martin Kleppman 撰写的“设计数据密集型应用程序”的副本,以更有说服力和细致入微地了解如何构建健壮的异步消息传递系统。 在反应式中,“背压”通常意味着“你的内存队列已满,现在你......?” 问号是回调和/或你发誓的地方。

  • Reactive 默认在当前线程上运行.. 这可能会导致奇怪的结果(包括阻塞程序)。 如果有疑问,请使用 subscribeOn( Schedulers.boundedElastic )。 一旦你把整个调度程序的混乱包裹起来,publishOn(..) 就更有针对性了。

  • “运营商”。 Spring 喜欢重命名事物。 这是“回调”的另一种说法。

  • 正如您所指出的,网络调用是(有效地)懒惰地评估的。 在您订阅/阻止之前什么都不会发生。 这使得触发请求、执行一些 CPU 工作、触发不同的请求、执行一些 CPU 工作等变得非常烦人。然后,在某个时候,检查所有请求,合并数据,然后移动在。 人们会向你推销诸如 zip() 之类的东西,但这不是一个好方法,因为让“一些 CPU 工作”与请求并行运行很麻烦。 如果你沿着这条路走下去,充其量你可以进入一些回调地狱。 回到 CompletableFutures 通常更容易,它具有更清晰的界面。

  • Flux 不会自动并行运行。 这很愚蠢,但你必须调用 parallel() 和 runOn()

  • WebFlux 主要使用 Monos,而不是 Fluxes。 去搞清楚。

  • 在 WebFlux 中处理错误和收集响应代码是一团糟,有几种不同的方法,都不好,都有自以为是的方面。 我喜欢 exchangeToMono()。

  • Mono 是 Deferred / Futures /etc,具有有限的功能,如果您不小心,这些功能实际上可能会在前台执行。

        CompletableFuture<Optional<ReturnType>> response = new CompletableFuture<>();
        client.post()
             .uri("why isn't this an argument to post???")
             .bodyValue("register a ridiculous number of callbacks to make a web call")
             .exchangeToMono(this::handleResponse)
             .subscribeOn(Schedulers.boundedElastic())
             .subscribe(resp -> response.complete(Optional.of(resp))
        ///Do some CPU work
        // make another request
        response.get(...bound the response with some time & wrap in exception handlers, if you like...)
             

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM