在ServerRequest的bodyToMono上使用subscribeOn时不起作用

时间:2019-10-11 08:49:51

标签: java spring-webflux project-reactor

我知道subscribeOn用于在订阅序列时切换执行线程,但是我发现它不适用于ServerRequest.bodyToMono / Flux

类似

Flux.just(1,2,3)
          .doOnNext(integer -> log.info("test {}",integer))
          .subscribeOn(Schedulers.elastic())
          .subscribe();

将更改执行线程

INFO 23313 --- [      elastic-2] c.a.p.m.f.service.router.TestService     : test 1
INFO 23313 --- [      elastic-2] c.a.p.m.f.service.router.TestService     : test 2
INFO 23313 --- [      elastic-2] c.a.p.m.f.service.router.TestService     : test 3

但是让我困惑的是

说我有一个Spring WebFlux路由器:

@Configuration
public class TestRouter {
    @Bean
    public RouterFunction<ServerResponse> testRouterFunction(TestService testService) {
        return route().path("/test", builder -> builder.nest(accept(MediaType.ALL),
          route -> route.PUT("/", req -> {
              Mono<String> valueMono = req.bodyToMono(String.class);
              return ServerResponse.ok().body(testService.test(valueMono), String.class);
          }))).build();
    }
}

和服务:

@Service
@Slf4j
public class TestService {
    public Mono<String> test(Mono<String> mono) {
        return mono
          .doOnSubscribe(subscription -> log.info("on subscribe"))
          .subscribeOn(Schedulers.elastic())
          .doOnNext(s -> log.info("received {}", s))
          .subscribeOn(Schedulers.elastic());
    }
}

基本逻辑是http对本地主机的请求:端口/测试将接收以纯文本形式发送到服务器的内容

无论我放在哪里,我都尝试使doOnNext在其他线程而不是Spring WebFlux的NIO线程上运行

subscribeOn

执行线程始终是NIO线程:

INFO 23200 --- [ctor-http-nio-4] c.a.p.m.f.service.router.TestService     : on subscribe
INFO 23200 --- [ctor-http-nio-4] c.a.p.m.f.service.router.TestService     : received test

感谢@MichaelBerry @SimonBaslé,你们两个都对我有很大帮助,请对两个答案都予以支持

简而言之,Reactor-netty将覆盖http订阅的subscribeOn,使用flatMap()在不同的subscribeOn()Mono/Flux上包含一个单独的publishOn()可以完成我的工作想要

1 个答案:

答案 0 :(得分:3)

这是您无法更改的事情-这只是链subscribeOn()被调用之前链中的最后一个subscribe()调用,因此,取决于WebFlux使用它想要的任何调度程序。在这种情况下,它看起来像是在NIO驱动的事件循环或类似事件中处理请求。

但是,您可以在链中包括一个flatMap()呼叫,您可以 指定一个单独的subscribeOn(),而不会覆盖。这可能是一个选择,具体取决于您的用例,因为您可以在flatMap()调用中定义的发布者中完成大部分工作。