Quarkus Cassandra客户端quarkusCqlSession.prepare挂起超时原因咨询
Quarkus CqlSession prepare方法挂起超时的原理说明
前置默认配置逻辑
- 当
quarkus.cassandra.use-quarkus-event-loop为默认值true时,Cassandra驱动会复用Quarkus底层Vert.x的事件循环线程池,处理所有和Cassandra集群交互的网络IO、请求响应回调逻辑。 - 你代码中调用的
quarkusCqlSession.prepare(ss)是同步阻塞方法,会一直阻塞当前运行线程,直到收到Cassandra集群返回的预编译语句响应才会返回。 - Vert.x的事件循环线程设计原则上不允许被阻塞,一旦阻塞会直接影响所有绑定在该线程上的IO任务调度。
调大quarkus.vertx.eventLoopsPoolSize生效的原因
你遇到的挂起本质是事件循环线程池的所有线程都被阻塞操作占满,Cassandra驱动没有可用线程处理预编译请求的响应:
- 初始配置下事件循环池大小仅为2,当这2个线程全部被类似你代码中的同步阻塞操作占用时,Cassandra驱动就算收到了集群返回的预编译结果,也没有可用的事件循环线程触发回调,导致
prepare()方法一直等不到返回信号,最终超时。 - 把池大小调至4后,可用事件循环线程数变多,就算有1~2个线程被阻塞操作占用,剩余的空闲线程仍然可以正常调度Cassandra的响应回调,
prepare()方法就能正常拿到结果返回,不会挂起。
补充说明
该方案属于临时规避方案,更合理的优化方向是避免在CDI Bean的构造函数中调用同步阻塞方法,可以改用prepareAsync()异步方法处理预编译逻辑,或者使用第二种方案配置quarkus.cassandra.use-quarkus-event-loop=false,让Cassandra驱动使用独立的IO线程池,完全不占用Vert.x的事件循环资源,从根源上避免阻塞事件循环的问题。
内容的提问来源于stack exchange,提问作者Paweł Nowakowski
相关产品推荐
相关产品推荐

