[英]How to execute blocking calls within a Spring Webflux / Reactor Netty web application
In my use case where I have a Spring Webflux microservice with Reactor Netty, I have the following dependencies:在我有一个带有 Reactor Netty 的 Spring Webflux 微服务的用例中,我有以下依赖项:
org.springframework.boot.spring-boot-starter-webflux
(2.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.springframework.boot.spring-boot-starter-data-mongodb-reactive
(2.0.1.RELEASE)org.projectreactor.reactor-spring
(1.0.1.RELEASE) org.projectreactor.reactor-spring
(1.0.1.RELEASE) 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
.对于一个非常特殊的情况,我需要从我的 Mongo 数据库中检索一些信息,并将其处理为通过我的反应式
WebClient
发送的查询参数。 As the WebClient
nor the UriComponentsBuilder
accepts a Publisher (Mono / Flux) I used a #block()
call to receive the results.由于
WebClient
和UriComponentsBuilder
接受发布者(Mono / Flux),我使用#block()
调用来接收结果。
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由于
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
My code snippet:我的代码片段:
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);
}
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.这适用于
spring-boot
版本 2.0.0.RELEASE,但由于升级到版本 2.0.1.RELEASE 并因此从reactor-core
升级到版本 0.7.6.RELEASE 它不再被允许。
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.我看到的唯一真正的解决方案是包含一个块(非反应性)存储库/mongo 客户端,但我不确定是否鼓励这样做。 Any suggestions?
有什么建议吗?
The WebClient
does not accept a Publisher
type for its request URL, but nothing prevents you from doing the following: WebClient
不接受其请求 URL 的Publisher
类型,但没有什么可以阻止您执行以下操作:
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;
}
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.如果有的话,这个新的反应器核心检查使您免于在 WebFlux 处理程序中间使用此阻塞调用使整个应用程序崩溃。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.