Quarkus Reactive Mutiny线程池管理及阻塞调用调度规则咨询
问题背景
- 本周刚开始使用Quarkus,此前接触过部分流式平台,尤其熟悉Scala生态中的http4s/fs2
- 使用Quarkus Reactive(搭配Mutiny)及各类响应式数据库客户端(Mutiny Reactive Postgres、响应式Elasticsearch等)时,对阻塞调用和线程池的正确管理存在疑问
- 已经理解Quarkus官方文档的说明:命令式代码或CPU密集型代码需要添加
@Blocking注解,调度到worker线程池执行,避免阻塞IO池
代码示例
public class Stuff { // 命令式,CPU密集型 public static int cpuIntensive(String arg) { /* ... */ } // 阻塞IO public static List<Integer> fetchFromDb() { /* ... */ } // 响应式IO public static Multi<String> fetchReactive() { /* ... */ } // 带CPU处理的响应式IO public static Multi<String> fetchReactiveCpuIntensive(String arg) { return fetchReactive() // 响应式获取数据 .map(fetched -> cpuIntensive(arg + fetched)); // CPU密集型操作 } }
核心疑问
- 从未添加
@Blocking注解的resteasy-reactive REST端点调用上述4类方法,各场景的执行逻辑是什么,会运行在哪个线程池? - 默认无
@Blocking注解的响应式REST端点中使用任意响应式客户端是安全的,但将阻塞调用封装到Uni中是否也能对不安全代码达到同样的保护效果?即所有返回Multi/Uni的代码是否都会默认在worker线程池运行? - 如何实现将响应式IO调用和CPU密集型任务调度到不同线程池的精细化控制。
补充说明
本问题核心并非询问
Uni/Multi返回类型和直接返回对象的差异,而是想了解任意时刻指定使用线程池的实现方式。
查阅Mutiny相关官方文档后,当前的理解如下:
- 如果端点有条件返回非阻塞结果(比如本地非阻塞缓存命中),可以直接在IO线程返回
- 缓存未命中时,既可以直接调用响应式客户端,也可以通过Mutiny将阻塞动作放到Quarkus worker线程池执行,同时Mutiny支持将任意流指定到特定线程池(executor)执行
- 响应式客户端或所有运行在非IO池的组件都可以安全调用,因为IO循环只会订阅worker池下发的数据
- 可单独配置CPU密集型线程池和IO密集型worker线程池,给对应的发射器指定executor即可实现最优方案,目前疑问已经基本解决
内容的提问来源于stack exchange,提问作者drobert
相关产品推荐
相关产品推荐

