Spring WebFlux控制器方法返回T转Mono<T>的两种实现方式对比
核心差异
两种写法完全不等价,核心区别在于getSome()的执行时机:
Mono.justOrEmpty(getSome()):立即同步执行getSome(),调用控制器方法的瞬间就会触发方法调用,计算出结果后再包装成Mono返回。这种写法存在两个明显问题:- 如果
getSome()包含阻塞IO、耗时计算逻辑,会直接占用WebFlux的IO请求线程,拖垮整个服务的请求吞吐量 - 即使后续订阅被取消,
getSome()的逻辑已经执行完成,会造成不必要的资源浪费
- 如果
Mono.fromSupplier(() -> getSome()):延迟执行getSome(),只有当返回的Mono被订阅时才会触发方法调用。这种写法完全符合响应式编程的懒加载规范:- 可以后续通过
subscribeOn手动指定调度器执行阻塞逻辑,不会占用IO线程,比如搭配Schedulers.boundedElastic()处理非响应式的阻塞操作 - 订阅取消的话不会触发
getSome()执行,能节省资源
- 可以后续通过
最优选择
优先使用Mono.fromSupplier的实现方式,如果你确认getSome()存在阻塞操作,还需要加上调度器切换,避免阻塞事件循环线程:
@GetMapping Mono<Some> read() { return Mono.fromSupplier(() -> getSome()) // 把阻塞操作切换到弹性线程池执行 .subscribeOn(Schedulers.boundedElastic()); }
只有当getSome()是纯粹的无阻塞、无副作用的计算逻辑(比如单纯的内存对象构造、参数拼接)时,两种写法的运行效果才没有明显差异,但即使是这种场景也更推荐用fromSupplier保持统一的响应式编程规范。
内容的提问来源于stack exchange,提问作者Jin Kwon
相关产品推荐
相关产品推荐

