2016-12-08 64 views
0

我有一个Java应用程序,每1分钟后安排一个cron作业。它运行在Glassfish 4上。我们将Hibernate与JTA Entity Manager一起使用,该容器管理用于执行SQL Server数据库上的查询。获取连接突然增长,导致服务器崩溃

JDBC连接池设置有:

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

运行22小时后的JDBC连接池统计数据:

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

获取连接数不断后10天左右下方例外递增和GlassFish 4崩溃。

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

请建议如何避免Glassfish的崩溃。

+0

你可以把运行作业的代码?你关闭关闭持久性管理器吗? – Gatusko

+0

根据文档 “容器管理的持久性上下文 - 作为名称状态 - 由企业容器管理,容器负责将持久性上下文注入到企业组件中,并且负责在当前的末尾处理它的处置交易。” 我们不能显式关闭容器管理事务中的实体管理器,因为它会抛出IllegalStateException异常。 – Rashmi

+0

这是示例代码示例: public Insight findInsightByName(String name){ \t Context ic; \t EntityManager em; \t Insight loc = null; \t尝试{ \t \t ic = new InitialContext(); \t \t em =(EntityManager)ic.lookup(kTIv5PU); \t \t LOC =(透视)em.createQuery( “从洞察d选择d WHERE d.name =:名称 ”) \t \t \t .setParameter(“ 姓名”,名字).getSingleResult(); \t \t \t } \t赶上(NamingException的前){ \t \t Logger.getLogger(TInsightDAO.class.getName())的日志(Level.SEVERE,空,前)。 \t} \t finally { \t \t em = null; \t \t ic = null; \t} \t return loc; } – Rashmi

回答

0
finally 
{ 
em = null; 
ic = null; 
} 

我认为现在的问题是,你永远不会commiting或关闭transacction 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(); 
} 

这是做transacction的正确途径。但是,你只调零值,仅此而已,这就是为什么你的池,而不是被关闭 Here is more documentation about Transactions

+0

您引用的示例是bean管理事务(BMT)。我正在使用容器管理事务(CMT)。您发送的文档链接包含有关此信息。所有关闭和回滚都由容器管理。如果我们试图明确关闭,它会抛出IllegalStateException。 – Rashmi

0

这很难说有什么问题的真正原因,但问题可能是所有连接都成为陈旧,因为很久没有使用过。

设置连接验证是一种很好的做法,它确保连接在外部服务器关闭时重新打开。

有一个彻底的文章约connection pools in Glassfish/Payara,结账特别是约(使用Derby DB中的例子)的部分:

要打开连接验证:

的asadmin设置 resources.jdbc- connection-pool.test-pool.connection-validation-method = custom-validation

asadmin set resources.jdbc-connection-pool.test-pool.validation-classname = org.glassfish.api.jdbc.validation。DerbyConnectionValidation

的asadmin 设置 resources.jdbc连接-pool.test-pool.is连接验证要求的=真

+0

我将打开连接验证和测试。您是否知道容器管理事务(CMT)中的hibernate实体管理器如何处理打开和关闭连接。它是否为每个执行的查询创建连接? – Rashmi

+0

在容器管理的事务中,hibernate每次都要求从容器中建立一个连接(我不确定是对每个查询还是每个事务一次,但我猜每个事务只有一次)。它不涉及打开/关闭它们,它只是获得连接。如果它是陈旧的,它不能做任何事情只是抛出一个错误。服务器应该确保连接没有失效并更新它。它可以通过很多方式来实现 - 从每次使用之前发布一个测试SQL,从更新空闲连接到验证连接。 – OndrejM

+0

“服务器应确保连接没有失效并续订它,它可以通过多种方式实现 - 从每次使用前发出一个测试SQL,将空闲连接更新为验证连接。“您能否详细说明如何在JTA中更新空闲连接 – Rashmi