2

私はこれを何時間も成功せずに行ってきました。マルチスレッドアプリケーションで DataSource をインスタンス化しています。すべてのスレッドは DataSource から接続を取得し、finally ブロックでそれらを閉じます (接続が確実に解放されるように、1 行ずつ行っています)。私が抱えている問題は、すべての接続で close メソッドが呼び出されても、DataSource によって解放されないことです。これは、DBCP データ ソースからsource.getNumActive()を出力する別のスレッドがあるためです。

これが基本的なセットアップです。

public class DataSourceHolder {
  private static DataSource source;
  static {
    get the data source either from jndi or created from scratch
  }
  public DataSource getDataSource() { return source; }
}

すべてのボイラープレートコードをカプセル化するための単純な JdbcPattern (スプリング JdbcTemplate のようなものですが、非常に単純) があります。これは次のように定義されます。

public class JdbcPattern {
  private DataSource source;
  public JdbcPattern(DataSource source) {
    this.source = source;
  }
  public int executeMethods(....) {
    Connection c = source.getConnection();
    try {
      .. do the statements
    } finally {
      try { c.close(); } catch (SQLException ignore) { }
    }
  }
  public List<?> queryMethods(....) {
  }
}  

最後に、プログラムの開始時に開始される 4 つのスレッドがあります。このスレッドはしばらくスリープ状態になり、ウェイクアップ時に DataSourceHolder プロバイダーの DataSource を使用して JdbcPattern をインスタンス化し、処理を開始します。作業が完了し、接続が閉じられると、DataSource によって実際には解放されません。DataSource の最大接続数に達すると、接続をインスタンス化できなくなるため、プログラムがフリーズします。

これをどう診断するか。

編集。これはTomcatで実行されています。一般的なメソッドはすべて catalina 共通ローダーによってロードされ、スレッドはいずれかの Web アプリケーション内で実行されます。クラスローダーの問題かもしれないと思っていました。

4

1 に答える 1

2

クローズの失敗を無視してはなりません。未チェックの例外でラップするか、ログに記録しますが、無視しないでください。プールへの接続を解放しようとしたときに奇妙なエラーが発生した場合は、わかりません。

プール DataSource 用の独自のラッパーを作成することをお勧めします。getConnection への呼び出しを、スタック トレースと接続の一意の識別子と共にログに記録できます。また、close を呼び出すときに、JdbcPattern に同じ方法でログを記録します。閉じられていない接続の識別子を見つけ、それらが getConnection スタック トレースからプールから取り出された場所に注意してください。サーバー内で DataSource ラッパーにこの分析を実行させることもできますが、これはコードが多くなり、エラーが発生する可能性が高くなります。最初に単純なロギングを試してみます。このロギングを製品に残すことを検討してください。ただし、通常のロギングしきい値よりも低くなります。また必要になります。

于 2012-06-10T00:30:37.360 に答える