Quarkus/PostgreSQL新增实体监听器后JDBC连接获取超时问题咨询
连接耗尽报错根因
该问题和监听器的字段赋值逻辑无关,是你使用的Quarkus 1.10.2.Final版本存在的已知框架bug导致的连接泄漏:
- 独立的
@EntityListener监听器在Quarkus 1.x版本中默认由CDI容器托管,触发@PrePersist/@PreUpdate回调时会出现事务上下文未正确传播的问题,无法复用当前事务已经持有的JDBC连接,每次回调都会向Agroal连接池申请新连接 - 回调处于事务提交前的同步阶段,申请的新连接不会被主动回收,只有请求结束后才会释放,当业务请求量较高时,短时间内会把默认20个连接全部占满,后续请求无法获取连接就会抛出
acquisition timeout异常
实体内部回调与独立监听器的差异
两者功能上没有区别,核心差异在调用上下文:
- 实体类内部的回调方法:属于实体对象的成员方法,执行时直接复用当前事务的上下文和已持有的JDBC连接,不会触发额外的CDI上下文切换、Bean初始化动作,不会重复申请连接
- 独立监听器类:由CDI容器管理实例生命周期,调用时需要完成上下文绑定、实例获取等逻辑,1.x版本Quarkus的相关扩展存在实现缺陷,容易出现上下文丢失、连接无法复用的问题
问题修复方案
将回调逻辑移到实体类内部可以避免上述问题,操作步骤如下:
- 删除实体类上的
@EntityListeners注解,删除对应的独立监听器类 - 在实体类内部新增非静态方法,添加
@PrePersist/@PreUpdate注解,在方法内完成createdBy、updatedBy字段的赋值 - 上线后观察连接池活跃连接数,稳定低于max-size阈值且无超时报错即可确认修复
如果调整后仍然偶发连接超时,建议升级Quarkus到2.0及以上版本,1.x版本的Hibernate ORM扩展存在多个和实体监听器相关的连接泄漏bug,升级版本可以彻底解决。
内容的提问来源于stack exchange,提问作者Rodrigo Bortolon
相关产品推荐
相关产品推荐

