我们使用的是内存数据库Exasol
,它确实提供了Ado.Net提供商,但它似乎缺少像ConnectionPooling
一些重要的功能,因此,每一个连接创建和销毁每请求,这会影响我们的性能,因为我们正在连接到AWS
上的托管数据库。我已经创建了一个简单的ConnectionPool
,有能力Resize
,请提出建议,如果这可以达到目的,或者我需要做更多的事情。自定义连接池
请注意我并不是在寻找代码审查,而是对我在当前实现中可能缺少的重要分析,以及是否有可用的实现(Nuget,Git),我可以重复使用。目前,我正在根据规模调整大小,如何根据时间达到相同的目标,在某些闲置时间内,应从队列中清除少量资源,从而减小规模。
重要细节:
- 使用
ConcurrentQueue
内部的线程安全的访问资源,从多个客户端 - 使用
AutoResetEvent
的等待和信号,如果池是空的 使用
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); } } } }); } }
感谢您的评论和重要细节。对于调整大小,由于连接对象是昂贵的资源,因此不像标准资源池,更喜欢受控制的调整大小机制,有时超过特定持续时间的空闲开放连接是纯粹的资源浪费,可以重新创建。在其他资源池中,他们通过加倍来增加收集的大小,而不是实际的对象,这些对象仍然需要根据需要创建/添加。 –
对于各种属性,正如您可能已经注意到的那样,它们是私有对象,但是与任何标准连接池用户都能够调整它一样,通过某些检查来避免异常 –
是的,那只是一个观察。我想你知道你在做什么,所以你的项目祝你好运:) – VMAtm