C# Exasol Ado.Net提供程序的自定义连接池
我们使用的是内存数据库C# Exasol Ado.Net提供程序的自定义连接池,c#,multithreading,ado.net,task-parallel-library,exasolution,C#,Multithreading,Ado.net,Task Parallel Library,Exasolution,我们使用的是内存数据库Exasol,它确实提供了Ado.Net提供程序,但它似乎缺少了一些重要的功能,如ConnectionPooling,因此每个请求都会创建和销毁连接,这影响了我们的性能,因为我们在AWS上连接到托管数据库。我已经创建了一个简单的连接池,可以调整大小,请建议这是否可以达到目的,或者我需要做更多的事情 请注意,我不是要查看代码,而是要对当前实现中可能缺少的内容进行批判性分析,如果有可用的实现(Nuget,Git),我可以重用它。目前我正在根据大小调整大小,如何根据时间实现相同的
Exasol
,它确实提供了Ado.Net提供程序,但它似乎缺少了一些重要的功能,如ConnectionPooling
,因此每个请求都会创建和销毁连接,这影响了我们的性能,因为我们在AWS
上连接到托管数据库。我已经创建了一个简单的连接池
,可以调整大小
,请建议这是否可以达到目的,或者我需要做更多的事情
请注意,我不是要查看代码,而是要对当前实现中可能缺少的内容进行批判性分析,如果有可用的实现(Nuget,Git),我可以重用它。目前我正在根据大小调整大小,如何根据时间实现相同的大小,在一定的空闲时间内,将从队列中清除少量资源,从而减少大小
重要细节:
ConcurrentQueue
从多个客户端对资源进行线程安全访问AutoResetEvent
等待,并在池为空时发出信号TPL
调整操作的大小,而不停止调用代码,我的理解是,即使在客户端调用返回时,这项工作仍然有效,因为它在Threadpool线程上运行
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);
}
}
}
});
}
}
类ExasolConnectionPool
{
///
///用于存储连接对象的线程安全队列
///
私有ConcurrentQueue ExasolConnectionQueue{get;set;}
///
///连接池上的连接数
///
私人国际连接账户;
///
///最大池大小
///
私有int MaxPoolSize{get;set;}
///
///最小池大小
///
私有int MinPoolSize{get;set;}
///
///池大小的增加
///
private int IncreasePoolSize{get;set;}
///
///池大小减少
///
私有int递减池大小{get;set;}
///
///连接池连接的连接字符串
///
私有字符串连接字符串{get;set;}
///
///连接池的自动重置事件
///
私有自动resetEvent ExasolConnectionPoolAre{get;set;}
///
///连接池特定的锁对象
///
私有只读对象锁对象;
///
///连接池构造函数
///
///
///
公共ExasolConnectionPool(字符串connectionString,int-poolSize=10)
{
//设置连接字符串
ConnectionString=ConnectionString;
//初始化连接队列
ExasolConnectionQueue=新的ConcurrentQueue();
//将初始连接集排队
对于(int计数器=0;计数器<池大小;计数器++)
{
var exaConnection=newexaconnection{ConnectionString=ConnectionString};
ExasolConnectionQueue.Enqueue(exaConnection);
}
//初始化锁对象
lockObject=新对象();
//设置连接队列计数
_connectionCount=池大小;
//最大池大小
MaxPoolSize=池大小;
//最小池大小
最小池大小=2;
增加池大小=5;
减少池大小=3;
ExasolConnectionPoolAre=新的自动存储事件(false);
}
///
///
///
///
公共连接ExageConnection()
{
//返回连接对象
EXAConnection返回连接;
//尝试从并发队列中退出连接对象
var validExasolConnection=ExasolConnectionQueue.TryDequeue(out-returnConnection);
//如果没有可用的有效连接,则使用自动重置信号机制等待
而(!validExasolConnection)
{
ExasolConnectionPoolAre.WaitOne();
validExasolConnection=ExasolConnectionQueue.TryDequeue(out returnConnection);
}
//线程安全连接计数更新
联锁减量(参考连接计数);
Task.Factory.StartNew(()=>
{
锁定(锁定对象)
{
if(_connectionCount>MinPoolSize)返回;
对于(变量计数器=0;计数器
{
锁定(锁定对象)
{
if(_connectionCount
您的池的实现很好。我不知道有哪种NuGet实现如此之小,并且对于您的案例来说不会过于复杂。我只想补充一些建议,你可以自己调查
TaskScheduler
是