ADO.NET 上に構築されたアプリケーションがあります。接続プールを利用できるいくつかの簡単なベスト プラクティスに従います。たとえば、データベースを使用するコード ブロックは次のようになります。
using( DbConnection dbConnection = GetDatabaseConnection() ) { doWork(); }
FWIW、GetDatabaseConnection について特別なことは何もありません。MSSQL Server 2000 を実行しているデータベースとの接続を確立します。実際には、次のように表示されます。
DbConnection GetDatabaseConnection() { return GetConnection(MyConnectionString); } DbConnection GetConnection(String connectionString) { try { SqlConnection dbConnection = new SqlConnection(connectionString); dbConnection.Open(); return dbConnection; } catch( InvalidOperationException ex ) { handleError(ex); throw; } catch( DbException ex ) { handleError(ex); } }
そのため、接続はブロック スコープの最後で破棄されます。しかし、アプリケーションのテストを開始したときに、ちょっとした問題が発生しました。私たちのアプリケーションは非常にバースト性があることがわかりました。つまり、非常におしゃべりになり、しばらく沈黙することがあります。その結果、接続を取得するために複数のスレッドを同時に起動できます。
10 個のスレッドがあるとします。作業のバッチ (作業のバッチを言い換えないでください) が到着し、いくつかのスレッドに分割されます。その後、各スレッドは接続を取得しようとしますが、私は InvalidOperationException に遭遇します。ConnectTimeout を調整しましたが、例外のバーストが発生するまで時間を延ばすだけです。「ワインドアップ」フェーズを過ぎると、アプリケーションは問題ありません。その後、再び静止し、接続が「なくなり」、プロセスが再び開始されます。
LoadBalanceTimeout の調整も試みましたが、引き続き例外が発生します。以前にこの問題を見たことがありますか? どんな考えでも...私は自分のいくつかを捨てます。
- 一部の接続を継続的に「ホット」に保つ
- 試行回数まで、接続を再度開くことを試みます
- 独自の接続プーリングを実装します (車輪の再発明には興味がありません)。
編集:
私が読んだほとんどのフォーラムでは、接続プールのサイズを大きくすることを思いとどまらせていました。デフォルトでは、接続プールには 50 接続の上限があります (これで十分です。増やす必要がある場合は、他の場所で何かが根本的に間違っています)。私が気付いたのは、ConnectTimeout が低い場合に InvalidOperationException が発生することです。接続のスピンアップが長すぎて、保留中の接続がすべてタイムアウトしたかのようです。
MARS は確かにオプションです... InvalidOperationException.Message のテキストは次のとおりです。
タイムアウトになりました。プールから接続を取得する前に、タイムアウト期間が経過しました。これは、プールされたすべての接続が使用中で、最大プール サイズに達したために発生した可能性があります。