Subject:
急需cnadoconpool使用方法及付费服务建议
[Print This Page]
Author:
skybluebird
Time:
2012-6-15 02:10
Subject:
急需cnadoconpool使用方法及付费服务建议
本人搞管理的,非专业程序员,但公司需要开发一套物流配货系统,需要尽量多的客户连接,最好能达到每台服务器能支持上千个连接,已用常规的方式开发了一套,服务器端有一个ADOCONNECTION,几十个ADOQUERY,每个对应一个DATASETPROVIDER,但无法满足负载需求,网上搜索了很久,觉得使用cnadoconpool应该是个好的选择,但具体的使用说明一直找不到,是不是应该这么用:
1. 在服务器端的远程数据模块加一个cnadoconpool,相关的属性设置好(没有说明,不知道该怎么设置)
2.在远程数据模块中的 oncreate事件中,用GetConnection,建立一个adoconnection
3.将所用的adoquery 的connection ,设置为这个新建立的adoconnection
4. 在远程数据模块的ondestroy事件中,加入ReleaseConnection方法
5. 所用了这个控件后,在客户端每次查询,更新数据后,是否还需要及时断开socketconnection,以减少服务器负担
不知道以上用法是否正确,服务器为 双核2.6,4G的内存,使用了这个控件,最多可以连接多少个用户
同时建议,对于需要使用贵公司控件的,而需要咨询的,可以考虑按天收取费用,毕竟,你们开发控件需要耗费大量的人力物力,再无偿提供服务,估计服务质量和速度肯定跟不上。没有服务,用户用起来也不放心。
Author:
shenloqi
Time:
2012-6-15 11:15
你好,根据你的描述,我不太能完全了解你的场景,我猜测你现在的做法是:有一个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 编辑
]
Author:
skybluebird
Time:
2012-6-18 14:41
Subject:
你好,shenloqi ,感谢你的回复
我的软件使用场景,正如你所猜测的一样。DataModule里的每个datasetprovider,都是无状态的,因此,应该使用你建议的方法二:封装一个单例的ADOConPool,在DataModule创建时不创建一个连接的ADOConnection,而是在有方法调用的时候获取一个ADOConnection,使用之后归还。
但具体的程序,应该怎么写。
1. 在服务器端的哪个地方(是不是 DataModule的 oncreate事件中)调用什么方法。
2.怎么判断使用完成,然后,在哪个地方(是不是DataModule的 onclose或者 ondestroy),调用什么方法归还。
Welcome to CnPack Forum (http://bbs.cnpack.org/)
Powered by Discuz! 5.0.0