2011-11-18 34 views
5

Glassfishで実行中のJava EEアプリケーションをjTDS経由でMSSQL Server 2008に接続しています。何らかの未知の理由により、要求中にデータベース接続が予期せず閉じられます。アプリケーションは巨大ですが、ここではエラーがどのように発生するかの概要を示します。GlassFish、jTDS、SQL Server 2008で予期せずデータベース接続が終了しました

Glassfishのセットアップ中に、asadmin create-jdbc-connection-poolasadmin create-jdbc-resourceの接続プールを作成します。データソースクラスはnet.sourceforge.jtds.jdbcx.JtdsDataSourceです。

Glassfishが登場すると、私たちはJNDIからデータソースを取得するServletContextListener.contextInitialized()の実装を呼び出します。データソースは静的変数に格納されます。

しばらくの間、すべてうまく行きます。すべての要求が処理され、接続は閉じられません。私たちのアプリケーションは、TimerとMDB(Message Driven Bean)EJBを使用して処理を実行します。

この

はサンプル onMessage()実装です:

public void onMessage(Message message) { 
    this.message = message; 
    this.connection = dataSource.getConnection(userName, password); 
    try { 
    doQuery1(); 
    doTransaction1(); 
    doTransaction2(); 
    doQuery2(); 
    doQuery3(); 
    } finally { 
    this.connection.close(); 
    this.connection = null; 
    } 
} 

は最終的に、我々は次の例外を取得するために開始する(たまたま一時間の間に約100回):例外がランダムJDBCで行わ

java.sql.SQLException: Invalid state, the Connection object is closed. 
    at net.sourceforge.jtds.jdbc.ConnectionJDBC2.checkOpen(ConnectionJDBC2.java) 
    at net.sourceforge.jtds.jdbc.ConnectionJDBC2.prepareStatement(ConnectionJDBC2.java) 
    at net.sourceforge.jtds.jdbc.ConnectionJDBC2.prepareStatement(ConnectionJDBC2.java) 
    at com.sun.gjc.spi.base.ConnectionHolder.prepareStatement(ConnectionHolder.java:475) 
    at com.acme.myejbs.MyMDB.doQuery2(MyMDB.java:123) 
    at com.acme.myejbs.MyMDB.onMessage(MyMDB.java:614) 
    at sun.reflect.GeneratedMethodAccessor115.invoke(Unknown Source) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java) 
    at java.lang.reflect.Method.invoke(Method.java) 
    at com.sun.enterprise.security.application.EJBSecurityManager.runMethod(EJBSecurityManager.java:1011) 
    ... 
    at $Proxy92.onMessage(Unknown Source) 
    at com.sun.messaging.jms.ra.OnMessageRunner.run(OnMessageRunner.java) 
    at com.sun.enterprise.connectors.work.OneWork.doWork(OneWork.java:77) 
    at com.sun.corba.ee.impl.orbutil.threadpool.ThreadPoolImpl$WorkerThread.run(ThreadPoolImpl.java:555) 

コール。クエリーの実行中にResultSet反復中に別の時が発生することがあります。

java.sql.SQLException: I/O Error: Connection reset by peer: socket write error 
    at net.sourceforge.jtds.jdbc.TdsCore.executeSQL(TdsCore.java) 
    at net.sourceforge.jtds.jdbc.JtdsStatement.executeSQLQuery(JtdsStatement.java) 
    at net.sourceforge.jtds.jdbc.JtdsPreparedStatement.executeQuery(JtdsPreparedStatement.java) 
    at com.acme.myejbs.MyMDB.doQuery2(MyMDB.java:126) 
    at com.acme.myejbs.MyMDB.onMessage(MyMDB.java:614) 
    ... 
Caused by: java.net.SocketException: Connection reset by peer: socket write error 
    at java.net.SocketOutputStream.socketWrite0(Native Method) 
    at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java) 
    at java.net.SocketOutputStream.write(SocketOutputStream.java) 
    at java.io.DataOutputStream.write(DataOutputStream.java) 
    at net.sourceforge.jtds.jdbc.SharedSocket.sendNetPacket(SharedSocket.java) 
    at net.sourceforge.jtds.jdbc.RequestStream.putPacket(RequestStream.java) 
    at net.sourceforge.jtds.jdbc.RequestStream.flush(RequestStream.java) 
    ... 44 more 
:私たちは、この例外を取得します(時間の間に5回)非常にまれなケースでも

java.sql.SQLException: Error in allocating a connection. Cause: This Managed Connection is not valid as the phyiscal connection is not usable 
    at com.sun.gjc.spi.base.DataSource.getConnection(DataSource.java:136) 
    at com.acme.myejbs.MyMDB.onMessage(MyMDB.java:614) 
    at sun.reflect.GeneratedMethodAccessor115.invoke(Unknown Source) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java) 
    at java.lang.reflect.Method.invoke(Method.java) 
    at com.sun.enterprise.security.application.EJBSecurityManager.runMethod(EJBSecurityManager.java:1011) 
    ... 
    at $Proxy92.onMessage(Unknown Source) 
    at com.sun.messaging.jms.ra.OnMessageRunner.run(OnMessageRunner.java) 
    at com.sun.enterprise.connectors.work.OneWork.doWork(OneWork.java:77) 
    at com.sun.corba.ee.impl.orbutil.threadpool.ThreadPoolImpl$WorkerThread.run(ThreadPoolImpl.java:555) 

:非常にまれなケースで

(時間の間に7回は)私たちは、この例外を取得します

はまれなケースでは、我々は、この恐ろしい例外(のjTDS内部NPE)を取得:

java.lang.NullPointerException 
    at net.sourceforge.jtds.jdbc.JtdsPreparedStatement.executeQuery(JtdsPreparedStatement.java) 
    at com.acme.myejbs.MyMDB.doQuery2(MyMDB.java:126) 
    at com.acme.myejbs.MyMDB.onMessage(MyMDB.java:614) 
    ... 

これがなぜ起こるか我々は見つけることができません。使用中の接続は、リクエスト中に1秒以上アイドル状態になることはありません。誰が接続を解除しているのかわかりません。それはネットワークの不安定性の可能性がありますが、jTDSはネットワーク関連の例外のみを生成するはずです。

もう1つの方法は、Glassfish接続プールのポリシーまたは構成です(Glassfishが物理的接続を途中で終了している可能性があります)。

最後に、MS SQL Server 2008はリモートから接続を切断することができますが、サーバーサイドを監視して問題が発生しているかどうかを確認するにはどうすればよいですか。

+0

に最も重要だと思いますか? – extraneon

+0

@extraneon Microsoft JDBCドライバはテストしませんでした。 jTDSに基づく永続性レイヤー全体があり、MSへの切り替えには数日かかるでしょう。 – fernacolo

+0

あなたのコードはSQLExceptionsをキャッチ/無視していますか?基本的なデータソースまたは接続プールを使用していますか? –

答えて

2

私は、これらのタイプの例外をほぼ正確に受け取ったアプリケーションを持っていました。私のマシンはすべて新品のサーバーで、すべてのネットワークカードはネットワーク速度を自動検出するように設定されていました。それらはすべて100MB /秒のHALFデュプレックスの古いスイッチに接続されていました。

自動検出ではなく、100MB /秒のHALFデュプレックス接続設定を明示的に使用するようにスイッチ上のすべてのマシンを設定することは、無限の時間をかけてソリューションを検索した後に私にとってうまくいきました。接続設定を確認する必要がありますか、試してみる必要があります(間違ったものを選択した場合は、リモートデスクトップ上のボックスに接続できないため、明らかになりますので、物理マシン)。

これをテストするにはかなり低い垂木です。データベースサーバにpingを実行しているワーカーマシンの1つからpingコマンドを入力してコマンドウィンドウを設定し、パケット損失を定期的に確認することができました。 NICの設定を変更して正しく設定したら、問題は完全に消え去った。この問題について議論しているインターネット上の記事がいくつかあります。 1)周期的で2)接続オブジェクトなどに問題があるように見えるため、追跡が困難です。

関連する問題