0

実稼働環境の 1 つでこの問題に直面しています。これは非常に頻繁に発生しますが、アプリケーションの同じセグメントで常に発生するとは限りません。かなりランダムです。

この環境に展開されたアプリケーションは、同じテクノロジと近い設定を使用した別のマシンに展開された他のアプリケーションと非常に似ていますが、エラーはこの環境でのみ発生するため、問題を特定するのは困難です。

いくつかのアップデートの変更により、これらのエラーが最近表示され始めたと言わざるを得ません。

Windows から Linux に移行されたアプリケーション

PostgresSQL 8.2 から 9.2

Tomcat 5 から Tomcat 6 へ

これらの変更はすべて、問題がまったく発生していない残りのデプロイ済みアプリケーションでも行われています。

アプリケーションで使用されるテクノロジーは次のとおりです。

休止状態 2.1.6

PostgreSQL 9.2

トムキャット 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"/>

問題を解決しようとしてエビクションがアクティブになりましたが、結果が得られなかったことに注意してください。

典型的な問題の流れは次のとおりです。

1.- 新しい Hibernate セッションが開かれます

2.- このセッションが開かれて接続されているかどうか、クエリの直前に確認します

3.- 開かれたセッションが有効であることをログで確認した後、例外が生成されます

- 追加した

エラーの 1 つの完全なスタック トレースは次のとおりです。

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: net.sf.hibernate.impl.SessionImpl@22880d66. 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 org.postgresql.jdbc3g.Jdbc3gConnection@1b0ca3f7 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 org.postgresql.jdbc3g.Jdbc3gConnection@1b0ca3f7 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 org.postgresql.jdbc3g.Jdbc3gConnection@1b0ca3f7 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 セッションを管理するクラスは、ServiceLocator というクラスです。このクラスのメソッド 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 org.postgresql.jdbc3g.Jdbc3gConnection@1b0ca3f7 is closed.

問題が Hibernate、Postgres、Tomcat のいずれに起因するものかはわかりません。Google でこのエラーについてほとんど何も見つけられなかったので、私に手を差し伸べていただければ幸いです。

追加情報や設定が必要な場合は、お問い合わせください。

前もって感謝します。

4

1 に答える 1

0

私はすでにこれを修正しました。

クォーツスレッドの問題でした。デフォルトでは、Quartz は異なるジョブの実行間で再利用されるスレッドのプールを管理します。接続の開閉を担当する私のクラス ServiceLocator は、ThreadLocal オブジェクトに基づいています。スケジュール ジョブの 1 つが適切に接続を閉じていなかったようで、その後、このジョブと同じスレッドで実行されたすべてのジョブでエラーが発生しました。

問題のあるジョブが何であるかを理解できず、最終的に行ったことは、Quartz のデフォルトの接続プールをカスタムのものに変更することでした.すべてのジョブのスレッドの量。

これは、誰かに役立つ可能性がある場合に備えて私が書いた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) { }

}
于 2013-04-10T12:25:07.777 に答える