2013-04-01 32 views
0

我在其中一個生產環境中遇到此問題。它經常發生,但並不總是在應用程序的相同部分,它非常隨機。net.sf.hibernate.util.JDBCExceptionReporter - Connection org.postgresql.jdbc3g.Jdbc3gConnection已關閉

部署在此環境中的應用程序與其他部署在不同機器上的應用程序非常相似,它們使用相同的技術和關閉設置,但錯誤僅出現在此環境中,因此很難找出問題。

我必須說,這些錯誤已經最近開始出現,因爲一些更新的變化:

應用程序從Windows遷移到Linux

PostgreSQL的8.2至9.2

Tomcat的5到Tomcat 6

所有這些更改也已完成,其餘的部署應用程序完全沒有遇到任何問題。

由應用程序使用的技術包括:

休眠2.1.6

的PostgreSQL 9.2

的Tomcat 6.0.35

在context.xml中的配置是:

<Resource name="jdbc/psa" auth="Container" type="javax.sql.DataSource" 
     driverClassName="org.postgresql.Driver" url="jdbc:postgresql://localhost:5432/psa?compatible=7.4" 
     username="xxx" password="xxx" maxActive="100" maxIdle="30" 
     maxWait="10000" factory="org.apache.tomcat.dbcp.dbcp.BasicDataSourceFactory" 
     defaultAutoCommit="false" removeAbandoned="true" 
     removeAbandonedTimeout="60" logAbandoned="true" validationQuery="select 1" 
     testOnBorrow="true" testOnReturn="true" testWhileIdle="true" 
     timeBetweenEvictionRunsMillis="300000"/> 

請注意,驅逐活動只是tryi以解決問題,但沒有結果。

一個典型問題的流程是下一個:

1.-一個新的Hibernate Session被打開

2:我只是在查詢前檢查,如果這個會話被打開並連接

3.-看到,這次會議開了是有效的,產生異常

--ADDED

日誌後

的錯誤之一的完整的堆棧跟蹤是這樣的:

29 03 2013 10:00:00 INFO EasyApScheduler_Worker-8 com.psa.accounting.eureca.logic.EurecaNLAccountingLogic - -- Process EURECA_NL starts 
    29 03 2013 10:00:00 INFO EasyApScheduler_Worker-2 com.psa.accounting.eureca.logic.EurecaSCAccountingLogic - -- Process EURECA_SC starts 
    29 03 2013 10:00:00 DEBUG EasyApScheduler_Worker-2 com.xeridia.persistence.ServiceLocator - Session opened: [email protected] Opened: true, Connected: true 
    29 03 2013 10:00:00 DEBUG EasyApScheduler_Worker-2 com.xeridia.persistence.ServiceLocator - [getConnection]|16|Thread[EasyApScheduler_Worker-2,4,main]| 
    29 03 2013 10:00:00 DEBUG EasyApScheduler_Worker-2 com.xeridia.persistence.ServiceLocator - [getConnection]|16|Thread[EasyApScheduler_Worker-2,4,main]|com.easyap.invoice.persistence.InvoiceDAOHibernate.<init>(InvoiceDAOHibernate.java:364) 
    29 03 2013 10:00:00 ERROR EasyApScheduler_Worker-8 net.sf.hibernate.util.JDBCExceptionReporter - Connection [email protected] is closed. 
    29 03 2013 10:00:00 DEBUG EasyApScheduler_Worker-2 com.xeridia.persistence.ServiceLocator - [getConnection]|16|Thread[EasyApScheduler_Worker-2,4,main]|com.psa.invoice.persistence.PSAInvoiceDAOHibernate.<init>(PSAInvoiceDAOHibernate.java:52) 
    29 03 2013 10:00:00 ERROR EasyApScheduler_Worker-8 net.sf.hibernate.util.JDBCExceptionReporter - Connection [email protected] is closed. 
    29 03 2013 10:00:00 ERROR EasyApScheduler_Worker-8 net.sf.hibernate.util.JDBCExceptionReporter - Could not execute query 
    java.sql.SQLException: Connection [email protected] is closed. 
     at org.apache.tomcat.dbcp.dbcp.DelegatingConnection.checkOpen(DelegatingConnection.java:398) 
     at org.apache.tomcat.dbcp.dbcp.DelegatingConnection.prepareStatement(DelegatingConnection.java:279) 
     at org.apache.tomcat.dbcp.dbcp.PoolingDataSource$PoolGuardConnectionWrapper.prepareStatement(PoolingDataSource.java:313) 
     at net.sf.hibernate.impl.BatcherImpl.getPreparedStatement(BatcherImpl.java:257) 
     at net.sf.hibernate.impl.BatcherImpl.getPreparedStatement(BatcherImpl.java:232) 
     at net.sf.hibernate.impl.BatcherImpl.prepareQueryStatement(BatcherImpl.java:65) 
     at net.sf.hibernate.loader.Loader.prepareQueryStatement(Loader.java:779) 
     at net.sf.hibernate.loader.Loader.doQuery(Loader.java:265) 
     at net.sf.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:133) 
     at net.sf.hibernate.loader.Loader.doList(Loader.java:1033) 
     at net.sf.hibernate.loader.Loader.list(Loader.java:1024) 
     at net.sf.hibernate.hql.QueryTranslator.list(QueryTranslator.java:854) 
     at net.sf.hibernate.impl.SessionImpl.find(SessionImpl.java:1544) 
     at net.sf.hibernate.impl.QueryImpl.list(QueryImpl.java:39) 
     at com.xeridia.persistence.BaseDAOHibernate.findByQuery(BaseDAOHibernate.java:312) 
     at com.xeridia.persistence.BaseDAOHibernate.findByQuery(BaseDAOHibernate.java:291) 
     at com.psa.invoice.persistence.PSAInvoiceDAOHibernate.getAccountingInvoicesWithNoProblem(PSAInvoiceDAOHibernate.java:215) 
     at com.psa.accounting.eureca.logic.EurecaNLAccountingLogic.getAccountingDataFromDB(EurecaNLAccountingLogic.java:469) 
     at com.psa.accounting.eureca.logic.EurecaNLAccountingLogic.process(EurecaNLAccountingLogic.java:207) 
     at com.psa.accounting.eureca.scheduler.CronEurecaNLAccounting.execute(CronEurecaNLAccounting.java:91) 
     at org.quartz.core.JobRunShell.run(JobRunShell.java:203) 
     at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:520) 

管理所有的Hibernate Session類是一類叫做服務定位。此類的方法的getConnection()返回一個新的連接和它的代碼是下一個:

synchronized (session) { 
       s = (Session) session.get(); 
       if ((s == null)||(!s.isOpen())) { 
        s = null; 
        s = getSessionFactory().openSession(); 
        if (s != null) { 
         log.debug("Session opened: " + s + ". Opened: " + s.isOpen() + 
           ", Connected: " + s.isConnected()); 
         printThreadDataForClosedConnections("[getConnection]"); 
        } 
        session.set(s); 
       } 
       if (!s.isConnected()) { 
        s.reconnect(); 
        log.debug("Session reconnected: " + s + ". Opened: " + s.isOpen() + 
          ", Connected: " + s.isConnected()); 
        printThreadDataForClosedConnections("[getConnection]"); 
       } 
      } 

對象「會話」被聲明爲:

public static final ThreadLocal session = new ThreadLocal(); 

以獲得用於不同的線程不同的會話,因此在線程之間不應該存在關閉會話的問題。

,你可以在上面的堆棧跟蹤看到的是,EasyApScheduler_Worker-2獲得,因爲if ((s == null)||(!s.isOpen())) {一個新的連接,但EasyApScheduler_Worker-8沒有,這意味着它的「會話」對象存在,並且是開放的或無法獲得連接,對應於錯誤的第一個跟蹤29 03 2013 10:00:00 ERROR EasyApScheduler_Worker-8 net.sf.hibernate.util.JDBCExceptionReporter - Connection [email protected] is closed.

我不知道問題是出自Hibernate,Postgres還是Tomcat。我在Google上幾乎沒有發現這個錯誤,所以我希望你能幫我一把。

請問您需要什麼額外的信息或設置,以幫助。

在此先感謝。

+1

這看起來像一個多線程的問題 - 你的第一個日誌來自一個'Thread'稱爲「EasyApAdminScheduler_Worker- 2「,並且您的異常來自稱爲」EasyApScheduler_Worker-8「的」Thread「。你是否在'線程'之間共享你的'會話'?這不太可取。無論如何,大概在第一個'Thread'關閉'Session'和使用它的第二個線程之間存在競爭風險。 –

+0

感謝您的回答。看看我原來的帖子,我添加了一些額外的信息。我寫的日誌跟蹤是錯誤的,它來自其他線程。你是對的,有2個Quartz進程同時運行,但是我有很多其他情況下只有一個Quartz進程。如果你願意,我可以從其他不同的更簡單的錯誤複製堆棧跟蹤。 – rocotocloc

+0

我仍然認爲這是一場比賽危險。遷移/更新通常會將這些內容帶到表面。調試種族危險是相當困難的,但您可以通過附加調試器並在關鍵部分放置中斷點開始。爲您的'ServiceLocator'編寫一個集成測試,它可以觸發大量'Thread's,也可能有助於深入瞭解它。 –

回答

0

我已經解決了這個問題。

這是石英線程的問題。默認情況下,Quartz管理在不同作業執行之間重用的線程池。我的類ServiceLocator負責打開和關閉連接,它基於ThreadLocal對象。看起來我的一個計劃任務沒有正確關閉它的連接,之後,在同一個線程上執行的所有作業都會導致錯誤。

我找不出什麼是有問題的工作,而我最終做的是改變Quartz的默認連接池爲一個自定義的連接池,以這樣的方式,我爲每個作業執行一個新的線程,而不是爲所有工作共享一定數量的線程。

這裏是石英自定義線程池,我的情況下,已經寫了它可能是有用的人:

public class SimpleNoThreadPooling implements ThreadPool { 

    public int getPoolSize() { 
     return 0; 
    } 


    public Log getLog() { 
     return LogFactory.getLog(SimpleNoThreadPooling.class); 
    } 

    public void initialize() throws SchedulerConfigException { } 

    class WorkerThread extends Thread { 

     private Runnable runnable = null; 

     /** 
     * <p> 
     * Create a worker thread, start it, execute the runnable and terminate 
     * the thread (one time execution). 
     * </p> 
     */ 
     WorkerThread(Runnable runnable) { 
      this.runnable = runnable; 
      start(); 
     } 

     public void run() { 
      if (runnable != null) { 
       try { 
        runnable.run(); 
       } catch (Exception exceptionInRunnable) { 
        try { 
         getLog().error("Error while executing the Runnable: ", 
          exceptionInRunnable); 
        } catch(Exception e) { 
         // ignore to help with a tomcat glitch 
        } 
       } 
      } 
     } 
    } 

    public boolean runInThread(Runnable runnable) { 
     new WorkerThread(runnable); 
     return true; 
    } 

    public void shutdown(boolean waitForJobsToComplete) { } 

} 
相關問題