Hibernate/HikariCP连接泄漏:关闭会话后连接仍活跃
Hibernate StatelessSession 结合 HikariCP 连接泄漏问题排查
问题背景
基于Tomcat9部署的对外数据库读写API应用,使用Hibernate与HikariCP时,在半复杂业务流程中出现StatelessSession导致的连接泄漏问题。
会话管理实现
会话获取方式
每次通过openSession()获取StatelessSession:
public static SessionFactory getSessionFactory() { if (sessionFactory == null) { sessionFactory = buildSessionFactory(); } return sessionFactory; } public static StatelessSession openSession() { return getSessionFactory().openStatelessSession(); }
会话错误处理与关闭逻辑
异常处理时调用resolveError(session),会话结束时调用closeSession(session):
public static void resolveError(StatelessSession session) { if (session != null && session.getTransaction() != null && session.getTransaction().getStatus() != null && session.getTransaction().getStatus() == TransactionStatus.ACTIVE) { session.getTransaction().rollback(); } } public static void closeSession(StatelessSession session) { if (session != null) { if (session.getTransaction() != null && session.getTransaction().getStatus() != null && session.getTransaction().getStatus() == TransactionStatus.ACTIVE) { session.getTransaction().commit(); } session.close(); session = null; } }
连接泄漏排查
Hikari连接池监控实现
通过JMX获取Hikari连接池的监控Bean:
public static HikariPoolMXBean getHikariPool() { try { MBeanServer bean = ManagementFactory.getPlatformMBeanServer(); ObjectName poolName = new ObjectName("com.zaxxer.hikari:type=Pool (HikariPool-1)"); return JMX.newMXBeanProxy(bean, poolName, HikariPoolMXBean.class); } catch (MalformedObjectNameException e) { e.printStackTrace(); } return null; }
监控状态对比
- 服务刚启动时状态:
[02-07-2024 17:06:16,640][DEBUG][] ================================================ [02-07-2024 17:06:16,640][DEBUG][] Idle Connections: 10 [02-07-2024 17:06:16,640][DEBUG][] Active Connections: 0 [02-07-2024 17:06:16,640][DEBUG][] Thread Awaiting: 0 [02-07-2024 17:06:16,640][DEBUG][] Total Connections: 10 [02-07-2024 17:06:16,640][DEBUG][] ================================================
- 涉事方法执行后数分钟状态:
[02-07-2024 17:06:16,640][DEBUG][] ================================================ [02-07-2024 17:06:16,640][DEBUG][] Idle Connections: 10 [02-07-2024 17:06:16,640][DEBUG][] Active Connections: 1 [02-07-2024 17:06:16,640][DEBUG][] Thread Awaiting: 0 [02-07-2024 17:06:16,640][DEBUG][] Total Connections: 11 [02-07-2024 17:06:16,640][DEBUG][] ================================================
涉事方法的会话操作逻辑
整理后的业务方法中会话相关代码:
private static final Object lock = new Object(); public Response method(DTO dto) { StatelessSession session = openSession(); ... try { validateDTO(dto); // hibernate-validator ... closeSession(session); synchronized (lock) { session = openSession(); session.getTransaction().begin(); ... session.getTransaction().commit(); ... closeSession(session); return Response.status(Response.Status.OK) .entity(...).build(); } } catch (Exception e) { ... resolveError(session); closeSession(session); return Response.status(Response.Status.INTERNAL_SERVER_ERROR) .entity(...).build(); } }
问题咨询
上述会话管理步骤是否存在错误?是否需要更换会话关闭方式?
内容的提问来源于stack exchange,提问作者G. Ciardini
相关产品推荐
相关产品推荐

