Spring boot WebClient 真的是异步的吗?

roa*_*oul -2 java asynchronous spring-boot spring-webflux

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

但我怀疑以下代码:

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

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

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

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

Pra*_*dey 6

WebClient用于Reactor Netty为 Java 提供完全异步的 NIO 网络库。

使用.block(),您将阻塞调用线程,这是不希望的。对于 I/O 调用,您应该使用.flatMap,它订阅内部流并在结果到达时动态合并结果。以你为例,我会这样做:

Mono.just(httpRequest)
    .flatMap(request -> request.exchange().bodyToMono(String.class))
    .map(response -> doWhateverToTheResponse(response))
    .subscribeOn(Schedulers.elastic())
    .subscribe();
Run Code Online (Sandbox Code Playgroud)

请注意,.flatMap()现在将订阅内部流。当响应返回时,它将进入map并且流将继续。当流在elastic线程上启动时,调用线程将变得空闲。

.block()除非绝对需要,否则切勿使用。使用它的一个用例:Kafka 的轮询循环。您希望确保在循环使用下一组记录之前已经处理了一组记录。.block()确保轮询线程保持阻塞,除非所有记录都被处理。

编辑:.flatMap()几个月前我写了一篇小文章。我觉得写的很好,你可以看看这里:

https://medium.com/swlh/understanding-reactors-flatmap-operator-a6a7e62d3e95

  • 调用线程变得空闲。I/O 调用将在针对 I/O 进行优化的弹性线程上进行。当然,该线程将变得空闲,并且 Netty 会切换到它自己的线程池。这个例子更多的是一个说明。 (3认同)