如何在Spring Webflux/Reactor Netty Web应用程序中执行阻止调用 [英] How to execute blocking calls within a Spring Webflux / Reactor Netty web application

查看:570
本文介绍了如何在Spring Webflux/Reactor Netty Web应用程序中执行阻止调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在使用带有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发送在一起的查询参数.由于WebClientUriComponentsBuilder都接受发布者(单声道/通量),因此我使用了#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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆