8

在我的用例中,我有一个带有 Reactor Netty 的 Spring Webflux 微服务,我有以下依赖项:

  • org.springframework.boot.spring-boot-starter-webflux(2.0.1.发布)
  • org.springframework.boot.spring-boot-starter-data-mongodb-reactive(2.0.1.发布)
  • org.projectreactor.reactor-spring(1.0.1.发布)

对于一个非常特殊的情况,我需要从我的 Mongo 数据库中检索一些信息,并将其处理为使用我的响应式发送的查询参数WebClient。由于WebClientnorUriComponentsBuilder接受 Publisher (Mono / Flux),我使用#block()调用来接收结果。

由于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/问题/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,它不再被允许。

我看到的唯一真正的解决方案是也包含一个块(非反应性)存储库/mongo客户端,但我不确定是否鼓励这样做。有什么建议么?

4

1 回答 1

6

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;         
}

如果有的话,这个新的反应堆核心检查使您免于在 WebFlux 处理程序中间使用这个阻塞调用使整个应用程序崩溃。

于 2018-04-10T08:14:24.610 回答