2016-12-08 62 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