You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring WebFlux控制器线程订阅差异:为何/mono与/mono/2线程不同?

问题:Reactor端点调用的线程差异原因

调用/mono端点时,控制台输出reactor-http-nio-3(IO主线程),但调用/mono/2端点时输出parallel-2。为何会出现这种差异?据我所知,Spring应始终在parallel/elastic线程上订阅。

相关代码

private static CountDownLatch countDownLatch = new CountDownLatch(1);

@GetMapping("/mono")
public Mono<Object> testMono(@RequestBody Mono<SignInRequest> body) {
  countDownLatch = new CountDownLatch(1);
  Mono<Integer> objectMono = Mono.just(25);
  return objectMono
      .flatMap(i -> body.flatMap(b -> doWork(i)));
}

@GetMapping("/mono/2")
public Mono<Object> testMono2(Integer a) {
  countDownLatch = new CountDownLatch(1);
  Mono<Integer> mono = Mono.just(99);
  Mono<Integer> objectMono = Mono.just(a);
  return objectMono
      .flatMap(i -> mono.flatMap(b -> doWork(i)));
}

private Mono<Object> doWork(Integer i) {
  return Mono.fromCallable(() -> {
    System.out.println(Thread.currentThread().getName());
    if(countDownLatch.await(i, TimeUnit.SECONDS)) {
      return i;
    }
    throw new RuntimeException("time exceeded");
  });
}

编辑补充

  • 示例代码可从对应代码仓库获取
  • 运行说明:需要运行在27017端口的MongoDB实例,数据库名为vilya_be(如有需要请修改用户名和密码);还需要运行在9092端口的Kafka实例
  • 为何未移除MongoDB和Kafka?因为我之前移除后,两个API均输出parallel-2,所以又恢复了它们。

解答

核心差异在于两个端点中上游Mono的数据源类型和Spring Web的线程调度策略:

  1. /mono端点的线程逻辑

    • @RequestBody Mono<SignInRequest> body是绑定到HTTP请求体的异步Mono,它的数据流由Spring Web的IO线程池(reactor-http-nio-*)负责推送。
    • flatMap操作默认会沿用上游的线程上下文执行后续逻辑,因此body.flatMap(...)会直接在IO线程上执行,doWork中的fromCallable不会主动切换线程,最终输出IO线程名称。
  2. /mono/2端点的线程逻辑

    • Mono.just(a)和Mono.just(99)都是同步、立即完成的Mono,属于纯CPU绑定的同步逻辑。
    • Spring Web为了避免IO线程被同步逻辑阻塞,会自动将这类纯同步的处理链切换到parallel线程池执行,因此doWork最终运行在parallel线程池的线程上,输出parallel-2。

关于移除MongoDB和Kafka后的统一线程表现:
当移除这些依赖后,Spring Web的自动配置会调整请求处理的上下文策略,原本绑定到IO线程的body数据源失去了异步触发条件,变成了类似同步数据源的行为,因此两个端点的处理逻辑都会被切换到parallel线程池执行,最终输出一致的线程名称。


内容的提问来源于stack exchange,提问作者SoT

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 03:24:53