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

Quarkus Reactive调用Hibernate Reactive报vertx事件循环线程阻塞异常

报错信息

IllegalStateException: The current thread cannot be blocked: vert.x-eventloop-thread-1

问题场景

使用Quarkus Reactive API从Hibernate Reactive服务拉取数据时固定触发上述错误,错误定位在存在内部方法调用的业务方法中。
报错截图

相关代码

Quarkus API层代码

@GET
@Path("/getEquipCls")
public Uni<List<Tuple>> getMethod() {
    return reactiveMethod();                
}

Hibernate Reactive服务层响应式方法代码

@Override
public Uni<List<Tuple>> reactiveMethod(params) {
    Long variable = methodForVariable.await().indefinitely();
    return reactiveMethod(variable);
}
已尝试操作

已尝试添加@Blocking、@NonBlocking注解修复问题,均未生效。

错误根因

Vert.x事件循环线程(即报错中的vert.x-eventloop-thread-1)严禁执行任何阻塞操作,代码中调用的.await().indefinitely()是典型的阻塞等待方法,直接触发了线程保护异常。
之前添加@Blocking注解不生效的核心原因是:该注解仅对CDI代理拦截到的外部调用公共方法生效,类内部自调用的方法、非公共方法不会触发拦截器逻辑,方法依旧运行在事件循环线程上,不会切换到阻塞工作线程池。

可行解决方案
  • 方案1(推荐,符合响应式编程规范):彻底移除阻塞调用,使用响应式链式操作替代主动等待,全程不阻塞事件循环,示例写法:
@Override
public Uni<List<Tuple>> reactiveMethod(params) {
    // 直接链式调用,不阻塞等待中间结果
    return methodForVariable.flatMap(variable -> reactiveMethod(variable));
}

该写法完全适配Quarkus Reactive与Hibernate Reactive的编程模型,无额外线程切换开销,是官方推荐的标准写法。

  • 方案2(适配必须使用阻塞逻辑的场景,不推荐):将包含.await().indefinitely()阻塞逻辑的代码拆分到独立CDI Bean的公共方法中,在该公共方法上添加@Blocking注解,保证方法被外部调用时会被拦截器切换到阻塞工作线程池执行,避免占用事件循环线程。注意不要在类内部直接自调用带@Blocking注解的方法,否则注解不会生效。

注意:Hibernate Reactive为全响应式框架,非必要不要混用阻塞API与响应式API,否则极易出现线程阻塞、上下文丢失等难以排查的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.01 12:25:00