1

Ado.Netプロバイダを提供するIn memoryデータベースExasolを使用していますが、重要な機能の一部が表示されていないようです(ConnectionPooling)。すべての接続が作成され、破棄されます。リクエストは、AWSというホストされたデータベースに接続しているため、パフォーマンスに影響しています。私は簡単なConnectionPoolを作成して、Resizeの能力を持っています。これが目的を果たすかどうか、あるいはもっと何かをする必要があるかどうかをお勧めします。Exasol Ado.Netプロバイダ用のカスタム接続プール

私は現在の実装で欠落している可能性のあるものについて、また再利用できる実装がある場合(Nuget、Git)のコードレビューを探しているわけではありません。現在、私はサイズに基づいてサイズを変更していますが、時間に基づいてどのように同じ時間を達成するかは、待ち時間から特定の期間を空けて、キューからリソースを少なくし、サイズを減らします。

重要な詳細:

  1. 使用ConcurrentQueue内部リソースへのスレッドセーフなアクセスのために、複数のクライアントからの
  2. 使用AutoResetEvent待機し、信号用プールが操作をリサイズするために
  3. 使用TPL空の場合は、呼び出し元のコードを停止することなく、クライアント呼び出しが返されても、私の理解はこの作業です。Threadpool thread

    class ExasolConnectionPool 
    { 
        /// <summary> 
        /// Thread safe queue for storing the connection objects 
        /// </summary> 
        private ConcurrentQueue<EXAConnection> ExasolConnectionQueue { get; set; } 
    
        /// <summary> 
        /// Number of connections on the Connection pool 
        /// </summary> 
        private int _connectionCount; 
    
        /// <summary> 
        /// Max Pool Size 
        /// </summary> 
        private int MaxPoolSize { get; set; } 
    
        /// <summary> 
        /// Min Pool Size 
        /// </summary> 
        private int MinPoolSize { get; set; } 
    
        /// <summary> 
        /// Increase in Pool Size 
        /// </summary> 
        private int IncreasePoolSize { get; set; } 
    
        /// <summary> 
        /// Decrease in Pool Size 
        /// </summary> 
        private int DecreasePoolSize { get; set; } 
    
        /// <summary> 
        /// Connection string for the Connection pool connections 
        /// </summary> 
        private string ConnectionString { get; set; } 
    
        /// <summary> 
        /// Auto Reset event for the connection pool 
        /// </summary> 
        private AutoResetEvent ExasolConnectionPoolAre { get; set; } 
    
        /// <summary> 
        /// Connection pool specific Lock object 
        /// </summary> 
        private readonly object lockObject; 
    
        /// <summary> 
        /// Connection pool constructor 
        /// </summary> 
        /// <param name="connectionString"></param> 
        /// <param name="poolSize"></param> 
        public ExasolConnectionPool(string connectionString, int poolSize = 10) 
        { 
         // Set the Connection String 
         ConnectionString = connectionString; 
    
         // Intialize the Connection Queue 
         ExasolConnectionQueue = new ConcurrentQueue<EXAConnection>(); 
    
         // Enqueue initial set of connections 
         for (int counter = 0; counter < poolSize; counter++) 
         { 
          var exaConnection = new EXAConnection {ConnectionString = ConnectionString}; 
    
          ExasolConnectionQueue.Enqueue(exaConnection); 
         } 
    
         // Initialize Lock object 
         lockObject = new object(); 
    
         // Set the Connection queue count 
         _connectionCount = poolSize; 
    
         // Max pool size 
         MaxPoolSize = poolSize; 
    
         // Min Pool Size 
         MinPoolSize = 2; 
    
         IncreasePoolSize = 5; 
    
         DecreasePoolSize = 3; 
    
         ExasolConnectionPoolAre = new AutoResetEvent(false); 
        } 
    
        /// <summary> 
        /// 
        /// </summary> 
        /// <returns></returns> 
        public EXAConnection GetConnection() 
        { 
         // Return ExaConnection object 
         EXAConnection returnConnection; 
    
         // Try Dequeue the connection object from the Concurrent Queue 
         var validExasolConnection = ExasolConnectionQueue.TryDequeue(out returnConnection); 
    
         // If No Valid connection is available, then wait using AutoReset signaling mechanism 
         while (!validExasolConnection) 
         { 
          ExasolConnectionPoolAre.WaitOne(); 
    
          validExasolConnection = ExasolConnectionQueue.TryDequeue(out returnConnection); 
         } 
    
         // Thread safe connection count update 
         Interlocked.Decrement(ref _connectionCount); 
    
         Task.Factory.StartNew(() => 
         { 
          lock (lockObject) 
          { 
           if (_connectionCount > MinPoolSize) return; 
    
           for (var counter = 0; counter < IncreasePoolSize; counter++) 
           { 
            var exaConnection = new EXAConnection {ConnectionString = ConnectionString}; 
    
            ExasolConnectionQueue.Enqueue(exaConnection); 
    
            Interlocked.Increment(ref _connectionCount); 
           } 
          } 
         }); 
    
         return (returnConnection); 
        } 
    
        /// <summary> 
        /// 
        /// </summary> 
        /// <param name="returnedConnection"></param> 
        public void ReturnConnection(EXAConnection returnedConnection) 
        { 
         ExasolConnectionQueue.Enqueue(returnedConnection); 
    
         Interlocked.Increment(ref _connectionCount); 
    
         ExasolConnectionPoolAre.Set(); 
    
         Task.Factory.StartNew(() => 
         { 
          lock (lockObject) 
          { 
           if (_connectionCount < MaxPoolSize * 1.5) return; 
    
           for (var counter = 0; counter < DecreasePoolSize; counter++) 
           { 
            EXAConnection exaConnection; 
    
            if (ExasolConnectionQueue.TryDequeue(out exaConnection)) 
            { 
             exaConnection.Dispose(); 
    
             exaConnection = null; 
    
             Interlocked.Decrement(ref _connectionCount); 
            } 
           } 
          } 
         }); 
        } 
    } 
    

答えて

1

プールの実装は問題ありません。私はNuGetの実装が小さいことを認識していませんし、あなたのケースでは過度に複雑ではありません。私はちょうどあなた自身で調べることができる提案の少量を追加したいです。ステファン・クリアリーによって

  1. StartNew is Dangerous資料では、ロジックのサイズを変更するために使用されている方法についての素晴らしい記事です。 「」現在実行は何でもTaskScheduler上で実行されます

    スレッド:最も重要な部分はこれです!

    だからあなたのコード時々UIスレッドコンテキストを使用して、アプリケーションのパフォーマンスが低下する可能性があります。問題がなければ(例:ASP.NETアプリケーションの場合)、問題はありませんが、そうでない場合はTask.Runメソッドを使用することをおすすめします。また、TPLベストプラクティスに関するスティーブンのブログを調べることもできます。

  2. 一般に、サイズ変更ロジックは単純な方法で行われます。サイズを2倍にすると、限界に達するとサイズが2倍になり、その逆も小さくなります。ユーザーにこの定数を管理する機能を提供すると、負のプールサイズなどのような奇妙なエラーが発生する可能性があります。

    したがって、プロパティの設定をprivateとし、私の場合はサイズ変更に関するプロパティを削除する必要があります。将来的には、アプリケーションの平均プールサイズに関する統計を収集し、そのパラメータをデフォルトとして使用することもできます。

+0

お読みいただきありがとうございます。リサイズの場合、接続オブジェクトは高価なリソースであるため、標準的なリソースプールとは異なり、制御されたリサイズメカニズムを優先します。一定期間を超えたアイドル状態の接続は、リソースの無駄です。他のリソースプールでも、必要に応じて作成/追加する必要がある実際のオブジェクトではなく、倍増することによってコレクションのサイズが大きくなります。 –

+0

あなたが気付いたように、それらはプライベートオブジェクトですが、標準接続プールのユーザーと同様に、例外を避けるために特定のチェックを使用して調整することができます。 –

+0

ええ、それは単なる観測でした。私はあなたが何をやっているのか知っていると思うので、あなたのプロジェクトで幸運を祈る:) – VMAtm