【问题标题】:Acquired Connections grows abruptly leading to server crashAcquired Connections 突然增长导致服务器崩溃
【发布时间】:2016-12-08 12:55:38
【问题描述】:

我有一个 Java 应用程序,它每 1 分钟安排一次 cron 作业。它在 Glassfish 4 上运行。我们将 Hibernate 与 JTA Entity Manager 结合使用,后者是用于在 SQL Server 数据库上执行查询的容器管理。

JDBC 连接池设置为:

初始和最小池大小:16
最大池大小:64
池调整数量:4
空闲超时:300
最大等待时间:60000

运行 22 小时后的 JDBC 连接池统计信息:

NumConnUsed 0 个
NumConnAcquired 14404count
NumConnReleased 14404count NumConnCreated 16count
NumConnFree 16count

获取的连接数不断增加,Glassfish 4 在大约 10 天后崩溃,以下异常。

RAR5117:无法从连接池 [com.beonic.tiv5] 获取/创建连接。原因:com.sun.appserv.connectors.internal.api.PoolingException: java.lang.RuntimeException: 在 XAResource.start 期间出现异常:

请建议如何避免 Glassfish 崩溃。

【问题讨论】:

  • 你能把作业的代码运行起来吗?您要关闭持久性管理器吗?
  • 根据文档“Container Managed Persistence Context——顾名思义——由企业容器管理。容器负责将Persistence Context注入到企业组件中,同时也负责其处置在当前交易结束时。”我们不能在容器管理事务中显式关闭实体管理器,因为它会抛出 IllegalStateException。
  • 这是示例代码示例: public Insight findInsightByName(String name) { Context ic;实体管理器 em;洞察 loc = null;尝试 { ic = new InitialContext(); em = (EntityManager) ic.lookup(kTIv5PU); loc = (Insight) em.createQuery("select d from Insight d WHERE d.name = :name ") .setParameter("name", name).getSingleResult(); } catch (NamingException ex) { Logger.getLogger(TInsightDAO.class.getName()).log(Level.SEVERE, null, ex); } 最后 { em = null; ic = 空; } 返回位置; }
  • 如何开始 cron 作业?通过 EJB 计时器?
  • 日志中是否有任何堆栈跟踪?什么是com.beonic.tiv5 - 你在使用一些自定义连接池吗?你的 Glassfish 崩溃是什么意思 - JVM 完全崩溃了?

标签: java sql-server hibernate jta glassfish-4


【解决方案1】:
finally 
{ 
em = null;
 ic = null; 
} 

我认为这是您从未提交或关闭交易的问题 Giving this example and documentation of JTA check 5.2.2

// BMT idiom
@Resource public UserTransaction utx;
@Resource public EntityManagerFactory factory;

public void doBusiness() {
    EntityManager em = factory.createEntityManager();
    try {

    // do some work
    ...

    utx.commit();
}
catch (RuntimeException e) {
    if (utx != null) utx.rollback();
    throw e; // or display error message
}
finally {
    em.close();
}

这是进行交易的正确方法。但是您只是将值归零,仅此而已,这就是您的池而不是关闭的原因 Here is more documentation about Transactions

【讨论】:

  • 您引用的示例是针对 bean 管理事务 (BMT)。我正在使用容器管理事务 (CMT)。您发送的文档链接包含有关此信息。所有关闭和回滚都由容器管理。如果我们尝试显式关闭,它会抛出 IllegalStateException。
【解决方案2】:

很难说问题的真正原因是什么,但问题可能是您的所有连接都因为长时间未使用而变得陈旧。

最好设置连接验证,确保连接在被外部服务器关闭时重新打开。

有一篇关于connection pools in Glassfish/Payara的详尽文章,特别是关于Connection validation的部分(在示例中使用Derby DB):

开启连接验证:

作为管理员设置 resources.jdbc-connection-pool.test-pool.connection-validation-method=custom-validation

作为管理员设置 resources.jdbc-connection-pool.test-pool.validation-classname= org.glassfish.api.jdbc.validation.DerbyConnectionValidation

作为管理员 放 resources.jdbc-connection-pool.test-pool.is-connection-validation-required=true

【讨论】:

  • 我将开启连接验证和测试。您是否知道容器管理事务(CMT)中的休眠实体管理器如何处理打开和关闭连接。它是否为每个执行的查询创建连接。
  • 在容器管理的事务中,hibernate 只是每次都从容器请求连接(我不确定是每个查询还是每个事务一次,但我猜每个事务只有一次)。它不处理打开/关闭它们,它只是获得一个连接。如果它是陈旧的,它不能做任何事情,只是抛出一个错误。服务器应确保连接不是陈旧的并更新它。它可以通过多种方式实现 - 从更新空闲连接到通过在每次使用前发出测试 SQL 来验证连接。
  • “服务器应该确保连接不是陈旧的并更新它。它可以通过多种方式做到这一点 - 从更新空闲连接到通过在每次使用前发出测试 SQL 来验证连接。”您能否详细说明如何在 JTA 中更新空闲连接。
  • 默认情况下,GlassFish/Payara 不更新任何连接。这必须在 JDBC 连接池上打开。如果您的数据库可用,最好使用表格或自定义打开验证。此外,打开连接泄漏检测应该会有所帮助。有关详细信息,请阅读答案中链接的博文。
猜你喜欢
  • 2013-01-16
  • 1970-01-01
  • 1970-01-01
  • 2014-04-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多