如何在Spring Webflux/Reactor Netty Web应用程序中执行阻止调用 [英] How to execute blocking calls within a Spring Webflux / Reactor Netty web application
问题描述
在使用带有Reactor Netty的Spring Webflux微服务的用例中,我具有以下依赖关系:
In my use case where I have a Spring Webflux microservice with Reactor Netty, I have the following dependencies:
-
org.springframework.boot.spring-boot-starter-webflux
(2.0.1.RELEASE) -
org.springframework.boot.spring-boot-starter-data-mongodb-reactive
(2.0.1.RELEASE) -
org.projectreactor.reactor-spring
(1.0.1.RELEASE)
org.springframework.boot.spring-boot-starter-webflux
(2.0.1.RELEASE)org.springframework.boot.spring-boot-starter-data-mongodb-reactive
(2.0.1.RELEASE)org.projectreactor.reactor-spring
(1.0.1.RELEASE)
在非常特殊的情况下,我需要从Mongo数据库中检索一些信息,并将其处理为与我的反应性WebClient
发送在一起的查询参数.由于WebClient
或UriComponentsBuilder
都接受发布者(单声道/通量),因此我使用了#block()
调用来接收结果.
For a very specific case I need to retrieve some information from my Mongo database, and process this into query parameters send with my reactive WebClient
. As the WebClient
nor the UriComponentsBuilder
accepts a Publisher (Mono / Flux) I used a #block()
call to receive the results.
由于reactor-core
(版本0.7.6.RELEASE)已包含在最新的spring-boot-dependencies
(版本2.0.1.RELEASE)中,因此无法再使用:block()/blockFirst()/blockLast() are blocking, which is not supported in thread xxx
,请参见-> https://github.com/reactor/reactor-netty/issues/312
Since reactor-core
(version 0.7.6.RELEASE) which has been included in the latest spring-boot-dependencies
(version 2.0.1.RELEASE) it is not possible anymore to use: block()/blockFirst()/blockLast() are blocking, which is not supported in thread xxx
, see -> https://github.com/reactor/reactor-netty/issues/312
我的代码段:
public Mono<FooBar> getFooBar(Foo foo) {
MultiValueMap<String, String> parameters = new LinkedMultiValueMap<>();
parameters.add("size", foo.getSize());
parameters.addAll("bars", barReactiveCrudRepository.findAllByIdentifierIn(foo.getBarIdentifiers()) // This obviously returns a Flux
.map(Bar::toString)
.collectList()
.block());
String url = UriComponentsBuilder.fromHttpUrl("https://base-url/")
.port(8081)
.path("/foo-bar")
.queryParams(parameters)
.build()
.toString();
return webClient.get()
.uri(url)
.retrieve()
.bodyToMono(FooBar.class);
}
这与spring-boot
2.0.0.RELEASE版本一起使用,但是由于升级到版本2.0.1.RELEASE,因此从reactor-core
升级到版本0.7.6.RELEASE,所以不再允许.
This worked with spring-boot
version 2.0.0.RELEASE, but since the upgrade to version 2.0.1.RELEASE and hence the upgrade from reactor-core
to version 0.7.6.RELEASE it is not allowed anymore.
我看到的唯一真正的解决方案是也包括一个块(非反应性)存储库/mongo客户端,但是我不确定是否鼓励这样做.有什么建议?
The only real solution I see is to include a block (non-reactive) repository / mongo client as well, but I'm not sure if that is encouraged. Any suggestions?
推荐答案
WebClient
不接受其请求URL的Publisher
类型,但是没有什么可以阻止您执行以下操作:
The WebClient
does not accept a Publisher
type for its request URL, but nothing prevents you from doing the following:
public Mono<FooBar> getFooBar(Foo foo) {
Mono<List<String>> bars = barReactiveCrudRepository
.findAllByIdentifierIn(foo.getBarIdentifiers())
.map(Bar::toString)
.collectList();
Mono<FooBar> foobar = bars.flatMap(b -> {
MultiValueMap<String, String> parameters = new LinkedMultiValueMap<>();
parameters.add("size", foo.getSize());
parameters.addAll("bars", b);
String url = UriComponentsBuilder.fromHttpUrl("https://base-url/")
.port(8081)
.path("/foo-bar")
.queryParams(parameters)
.build()
.toString();
return webClient.get()
.uri(url)
.retrieve()
.bodyToMono(FooBar.class);
});
return foobar;
}
如果有的话,这种新的反应堆堆芯检查可以使您避免在WebFlux处理程序中间通过此阻塞调用使整个应用程序崩溃.
If anything, this new reactor-core inspection saved you from crashing your whole application with this blocking call in the middle of a WebFlux handler.
这篇关于如何在Spring Webflux/Reactor Netty Web应用程序中执行阻止调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!