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

Quarkus+Vert.x部署双Verticle查询多数据库未并行执行问题咨询

问题原因

  • Verticle串行部署:你当前的部署代码中使用await().indefinitely()阻塞等待第一个Verticle部署完成后,才开始部署第二个Verticle,导致两个Verticle的EventBus consumer注册存在时间差。如果事件触发时第二个consumer还未完成注册,就会出现任务触发延迟,看起来像串行执行。
  • 查询结果返回时间差:如果两个Verticle的handler触发时间(即>>> Start Handler日志的时间戳)几乎一致,那日志呈现的串行输出只是因为fruit库查询响应更快,结果先全部返回打印,bill库查询响应慢200ms左右,所以后输出,实际查询已经是并行触发的,只是结果返回时序导致看起来串行。

调整方案

方案1:并行部署Verticle

如果要保留现有Verticle的实现,把串行部署逻辑改为并行部署,确保两个Verticle的consumer同时注册完成:

public void init(@Observes StartupEvent event,
                 Vertx vertx,
                 DbTestVerticle dbTestVerticle,
                 DbFruitVerticle dbFruitVerticle) {
    // 同时触发两个Verticle部署,等待全部部署完成后再结束启动逻辑
    Uni.join().all(
            vertx.deployVerticle(dbTestVerticle),
            vertx.deployVerticle(dbFruitVerticle)
    ).await().indefinitely();
}

调整后两个consumer会几乎同时注册完成,此时再publish事件,两个查询任务会同时触发。

方案2:直接用Mutiny流组合实现并行查询(更推荐)

这类并行拉取多数据源的场景不需要单独创建Verticle,直接通过Mutiny的流组合能力即可实现并行,代码更简洁,没有EventBus通信的额外开销:

@ApplicationScoped
public class DbQueryService {
    @Inject
    @ReactiveDataSource("fruit")
    PgPool pgPoolFruit;

    @Inject
    @ReactiveDataSource("bill")
    PgPool pgPoolBill;

    // 并行拉取两个库的数据,返回Tuple封装的两个结果集
    public Uni<Tuple2<List<Fruit>, List<Bill>>> parallelGetAll() {
        return Uni.join().all(
                // fruit库查询逻辑
                pgPoolFruit.query("select f.* from fruit f").execute()
                        .onItem().transformToMulti(set -> Multi.createFrom().iterable(set))
                        .map(this::mapFruit)
                        .collect().asList(),
                // bill库查询逻辑
                pgPoolBill.query("select b.* from bill b").execute()
                        .onItem().transformToMulti(set -> Multi.createFrom().iterable(set))
                        .map(this::mapBill)
                        .collect().asList()
        ).asTuple();
    }

    private Fruit mapFruit(Row row) {
        // 映射逻辑
    }

    private Bill mapBill(Row row) {
        // 映射逻辑
    }
}

该方案中两个查询是冷流,调用join时会同时订阅两个流,触发并行执行,不需要依赖EventBus通信。

最佳实践

  • 无依赖关系的Verticle部署要并行执行,不要串行加await阻塞,避免不必要的启动延迟和注册时序问题。
  • 多数据源并行查询场景优先使用Mutiny的Uni.join()/Multi.join()能力组合流,不要依赖EventBus广播触发任务,避免消息投递时序问题和额外的通信开销。
  • 所有IO操作都使用响应式客户端,不要在EventLoop线程中执行任何阻塞操作,避免EventLoop被阻塞导致任务串行执行。
  • 验证并行是否生效可在任务触发入口打印时间戳,不要只看结果输出的时序,结果返回的时间差会导致输出看起来串行,不代表任务没有并行触发。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 09:24:03