5

Glassfishで実行されているJavaEEアプリケーションがあり、jTDSを介してMSSQLServer2008に接続しています。なんらかの理由で、データベース接続がリクエスト中に予期せず閉じられます。アプリケーションは巨大ですが、エラーがどのように発生するかの概要は次のとおりです。

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

Glassfishが起動すると、ServletContextListener.contextInitialized()の実装が呼び出され、JNDIからデータソースがフェッチされます。データソースは静的変数に保存されます。

しばらくの間、すべてがうまくいきます。すべてのリクエストが処理され、接続は閉じられません。このアプリケーションは、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;
  }
}

最終的に、次の例外が発生し始めます(1時間に約100回発生します)。

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)

例外はランダムなJDBC呼び出しで発生します。ResultSetの反復中の場合もあれば、クエリの実行中の場合もあります。

非常にまれなケース(1時間に7回)では、次の例外が発生します。

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)

また、非常にまれなケース(1時間に5回)では、次の例外が発生します。

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

まれに、この恐ろしい例外(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はリモートで接続を切断する可能性がありますが、サーバー側を監視して、接続が発生しているかどうかを確認するにはどうすればよいでしょうか。

4

2 に答える 2

2

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

そのスイッチ上のすべてのマシンを、自動検知ではなく100MB /秒のHALF二重接続設定を明示的に使用するように設定することは、解決策を数え切れないほど検索した後、私にとってうまくいきました。接続設定を確認するか、実験する必要があります(リモートデスクトップ経由でボックスに接続できないため、間違った設定を選択した場合は明らかです。そのため、物理マシン)。

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

于 2011-11-23T13:31:35.170 に答える
1

SQL Server Profilerを使用してみてくださいhttp://msdn.microsoft.com/en-us/library/ms187929.aspx イベントが含まれているため、テンプレート「Standard」から始めることができます:Audit Login、Audit Logout、ExistingConnection http:/ /msdn.microsoft.com/en-us/library/ms190176.aspx 私はそれらがあなたにとって最も重要だと思います

于 2011-11-25T21:04:37.700 に答える