你好,根据你的描述,我不太能完全了解你的场景,我猜测你现在的做法是:有一个DataModule,上面放了一个ADOConnection和很多ADOQuery,这些ADOQuery的连接都是那个ADOConnection;然后通过SocketServer之类的服务器,每个客户端都持有一个DataModule的引用或所有的客户端都共享同一个DataModule?
如果是这样的情形,如果客户端很多,且保持着连接,那么要么就是有太多的ADOConnection占用了大量数据库资源,要么就是大量请求至同一个ADOConnection,导致即使不考虑事务或并发的带来的问题也会出现单个连接无法应对太多客户端请求的情形。
当然,服务器承受不了那么多负载的情形有很多,若是瓶颈的确在于上面分析的情况的话,那么简单的应对方法有两种:
方法一:对DataModule进行池化,如果你的DataModule是有状态的,那么要么不能池化,要么需要修改客户端保存状态,每次方法调用时传递状态。若池化DataModule可以满足你的要求,可以仿照TCnADOConPool的方式实现,这样做工作量不大,且可以获得请求过多时等待超时等方法带来的好处。
方法二:封装一个单例的ADOConPool,在DataModule创建时不创建一个连接的ADOConnection,而是在有方法调用的时候获取一个ADOConnection,使用之后归还。这样做,可以避免太多数据库连接带来的性能问题,又可以避免一个连接带来的性能瓶颈问题。
此外,如果是有很多个连接,但是这些连接大部分都是空闲的(即调用服务器方法不是很频繁),那么建议你可以用以IOCP或其他方法实现的SocketServer,这些SocketServer可以更好的处理大量的活的连接。
TCnADOConPool的使用方法,在其源代码中有一定的注释(在其父类CnObjectPool.pas中),但是没有一个系统的文档。
我把几个比较重要的类型的注释复制到这里:
{ 获取池对象的选项
goNone 无任何特殊处理
goReInit 需要初始化,不允许多次引用
goMutex 不需要初始化,不允许多次引用
} //对于ADOConnection来说,一般是不允许重用的,所以建议设置为goReInit或goMutex,如果是goReInit,则可以通过在重新初始化方法中对数据库连接进行连接选项的复位
TCnObjectPoolGetOption = (goNone, goReInit, goMutex);
{ 释放池对象的选项
roNone 仅仅减少引用计数
roReInit 要求重新初始化
roDelete 从对象池中删除对象
roFree 释放该对象
} //对ADOConPool来说,可以在出错或连接断开之后要求连接池释放该对象,如果对连接的选项进行了修改,可以要求复位,如果这个对象你想据为己有,自己释放他,可以选择要求对象池仅仅删除即可,注意从连接池删除的对象不能是多次引用的对象,因此必须配合goReInit或goMutex使用,这点在对象池中没有进行检查。
TCnObjectPoolReleaseOption = (roNone, roReInit, roDelete, roFree);
{ 获取池对象的结果
grSuccess 成功
grReuse 多次引用的对象
grInitFail 初始化失败
grGetFail 获取失败
grGetError 获取的结果有误
grWaitFail 等待超时
} //从对象池获取对象的结果
TCnObjectPoolGetResult = (grSuccess, grReuse, grReinitFail, grGetFail, grGetError, grWaitFail);
{ 池中无空闲对象时的策略
(如果对象需要被初始化或互斥则必须使用计数为0的对象)
bpWait 等待空闲的对象
bpGetFail 直接返回失败
bpReuse 多次引用对象
} //对象池所有对象都被使用的策略,ADOConPool可以等待,配合对象池的Timeout属性使用
TCnObjectPoolBusyPolicy = (bpWait, bpGetFail, bpReuse);
{ 池中对象都达到引用最大值时的策略
bpWait 等待空闲的对象
bpGetFail 直接返回失败
} //如果设置了重用对象的重用数,那么,当所有对象都到达重用最大值的时候,采取的方法,对于ADOConPool不建议重用,因此在不重用的时候,此选项设置没有什么影响
TCnObjectPoolPeakPolicy = bpWait..bpGetFail;
{ 获取池对象的策略
gpReuse 使用引用计数最小的对象
gpReuseMaxWorEff 引用计数最小的工作效率(平均工作时间)最高的
gpReuseMinWorkCount 引用计数最小的工作次数最少的
gpReuseMaxWorkCount 引用计数最小的工作次数最多的
gpReuseMinWorkTime 引用计数最小的工作时间最少的
gpReuseMaxWorkTime 引用计数最小的工作时间最多的
gpMaxWorkEff 工作效率最高的(无引用高于有引用)
gpMinWorkCount 工作次数最少的(无引用高于有引用)
gpMaxWorkCount 工作次数最多的(无引用高于有引用)
gpMinWorkTime 工作时间最少的(无引用高于有引用)
gpMaxWorkTime 工作时间最多的(无引用高于有引用)
} //这是怎么从对象池中挑选对象的策略,对于ADOConPool可以选择优先使用工作效率最高的或工作时间最少的对象
TCnObjectPoolGetPolicy = (gpReuse,
gpReuseMaxWorkEff,
gpReuseMinWorkCount, gpReuseMaxWorkCount,
gpReuseMinWorkTime, gpReuseMaxWorkTime,
gpMaxWorkEff,
gpMinWorkCount, gpMaxWorkCount,
gpMinWorkTime, gpMaxWorkTime);
[ 本帖最后由 shenloqi 于 2012-6-15 11:52 编辑 ]
|