Glassfishで実行中のJava EEアプリケーションをjTDS経由でMSSQL Server 2008に接続しています。何らかの未知の理由により、要求中にデータベース接続が予期せず閉じられます。アプリケーションは巨大ですが、ここではエラーがどのように発生するかの概要を示します。GlassFish、jTDS、SQL Server 2008で予期せずデータベース接続が終了しました
Glassfishのセットアップ中に、asadmin create-jdbc-connection-pool
とasadmin 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はリモートから接続を切断することができますが、サーバーサイドを監視して問題が発生しているかどうかを確認するにはどうすればよいですか。
に最も重要だと思いますか? – extraneon
@extraneon Microsoft JDBCドライバはテストしませんでした。 jTDSに基づく永続性レイヤー全体があり、MSへの切り替えには数日かかるでしょう。 – fernacolo
あなたのコードはSQLExceptionsをキャッチ/無視していますか?基本的なデータソースまたは接続プールを使用していますか? –