我的若干数据源(有DB、MSMQ、COM、File、FTP、TCP、HTTP、POP3等)都是数组对象实例,有多少种有多少个是由用户设置决定的,而且是不可能用多个队列来处理,因为这部分是负责通讯的,不处理数据,只是收和发,对它来说一切都一样,都是DATA,感谢交流,请给些好的建议
解决方案 »
- 北京有delphi的程序员吗!
- 【菜鸟100分】循环问题
- outlookbar
- 文件的问题 (解决问题不胜感激啊天天等)
- 请问一个关于Destroy的问题
- 急。。。急。。。一个时间运算问题(20分)
- 有在北京的同行吗?请教几个非技术问题
- 许久了,俺一直打算想学一学DELPHI,所以前些天买了N本DELPHI教程,但感觉基础不扎实,学起来有些不顺手。请问各位大哥,有什么介绍QBJECT PASCAL的精典教程吗??
- 请教数据库共享问题
- 用什么方法看懂国外的DELPHI网站,用什么翻译系统,推荐几种??
- 用鼠标点击DBGrid时,如何将DBGrid里的所在列的字段名取出,在线等
- 去哪找rnaui.dll啊?
在我的系统里面也有这个问题,也就是端口数量是由用户自己决定,且每个端口的类型也可能不一样,比如A端口也C端口是用a协议通过,B端口用b协议,D端口用c协议,但通过协议是已知的,即我的程序知道有多少种通过协议,我为每一种通讯协议建立了一个队列,处理该协议的程序肯定是确定的。
用同一种协议的端口只对同一个队列操作。所以队列是确定的,而不是未知的。
在你的程序里也一样,如果按我的思路处理的话最多也就是8个队列。
OK?
ADO每个连接同时只能开一个事务,而把多个线程的操作作为一个事务是不合理的.或者说,把一个事务分到多个线程中去是不合理的.
至于性能问题,我觉得可以这样做:
1.维护一个全局的Connection对象缓冲区,每个线程在缓冲区中寻找空闲的对象使用,并把它标记为非空闲.
2.如果已经没有空闲的对象,就要创建一个对象.
3.线程结束时,不释放Connection对象,只是结束事务,并把它所用的对象标为空闲.
4.缓冲区的大小应该是动态增/减的.
此外,因为要在不同的线程中使用这些Connection对象,创建它们的线程应该是自由线程,或用CoMarshalInterThreadInterfaceInStream把它们分别列集到一段内存(流)中,在缓冲区中保留这段内存,线程在使用它们时再用CoGetInterfaceAndReleaseStream进行散集.
mrzho(mrzhou):我的程序只用了一个连接,且实现了和你一样的目的。
两位高人显然有不同见解,这一块也是最让我困惑的地方,大家再给解释一下吧!
如果可能,为了性能优化,尽量不要使关键的部分串行化。用队列、互斥锁就会导致串行化。最好的办法是维护一个预先初始化的ADO对象池,其中的ADO对象都处于活动状态,这样做允许最大并发的数量等于对象池的大小,根据事务的活动程度选择适当的池容量。如果可能的话,还可以考虑动态调整对象池的策略,以适应峰值流量和空闲期。
我的全文检索引擎服务器程序就使用了这种办法的线程池响应客户连接,初始值=8,最大峰值=256,持续值=32,空闲时限=8s,只要硬件平台不要太差,高负载的流量毫无问题。
1.ADOConnection的数量(因为若干数据源对象的数量不定)
2.数据的数量(峰值和空闲无法感知)
各位有什么高见再说说
一般DBMS在处理事务时是以连接为单位的.以ADO为例:当调用ADODB.Connection.CommitTrans,所有用这个连接所作的操作都会被提交;当调用ADODB.Connection.RollbackTrans时所有用这个连接所作的操作都会被放弃.所以,如果几个操作不是一个事务,它们就不应该同时使用一个连接.在串行操作中不存在这个问题,因为大家不会同时使用一个连接,但在多线程时就一定要注意这一点了.
当然,这样的话实例的个数是可控的
自然,ADO就只有一个啦
不知这样能不能满足你呢???
有空的话,请大家看看:
http://www.csdn.net/expert/topic/745/745893.xml?temp=.265362
我觉得不存在上面所说的那些情况。
如果必须考虑性能,采用plainsong(轻风)和 mrzho(mrzhou)的方案都是可行的,这也是消息、交易中间件中常用的技术,不过目前各厂家的中间件价格较贵,多应用于银行、电信等大的项目中,如果在小型项目中可以考虑COM+的池和MSMQ的队列,如果非要自己做,麻烦其实不小,还需要考虑网络状况、超时等等,反正我现在不会再花工夫去做现成的东西了,研究除外
mrzho(mrzhou)只用一个数据库连接的技术是正确的,但并不是说只用一个是科学的,一般是采用plainsong(轻风)的池技术,n个数据库连接共享,同时用队列技术管理m个请求,这就要求请求最好是无状态的
此外,事务的功能不只是把一组操作变成一个元操作,在很多情况下,它还是DBMS管理访问锁的一个单位.比如在这条语句:
Select * from MyTable Where ID < 50 For Update;
就会把MyTable中ID<50的所有记录锁住,不允许其它连接对这些记录进行修改操作,直到该事务结束.这种功能在UPDATE操作中很有用.
如果使用连接池的方法,数据库连接时间的影响基本上解决了,这样应该要比用一个连接快一些(也可能快的有限),不过程序就复杂很多了.
用几个线程负责接收数据,一个线程负责把接收到的数据入库,这种方式好象叫生产者-消费者模式.如果入库的速度跟不上,可以增加几个线程进行入库(增加消费者,也算是响应国家的"刺激消费"的号召吧).
CreateIoCompletionPort
GetQueuedCompletionStatus
PostQueuedCompletionStatus另外Delphi6运行库的
ISAPIThreadPool.pas 有完整的线程池实现代码 在\source\internet\
学习先
至于"数据库的连接断开对性能影响",可以不用考虑,SQL有连接池的
But, here, you need to decide whether you want to go synchronously or asynchronously.
Mutex is a synchronous lock. Asynchronous would be more complex.
Actually, if you configure the lower limit and upper limit to 1, it is equivalent to mrzhou's solution.
我也做过类似的SERVICE,你所说的两个问题
1.有N条数据到达就要有N个ADO对象实例和对同一数据源的N个连接
连接是限制的,达到一定的数目时肯定出错,所以这种方案在流量不大时可取,但如果流量很大肯定会出现问题,不是很好的解决方案。
2.数据高峰时,频繁的进行对象的创建释放、数据库的连接断开对性能影响很大
确实值得考虑,对象的创建和连接的建立对性能影响确实很大。完全可以创建一个全局的连接对象(但这个对象是否始终保持联接则要考虑了),你的数据处理不是都要调用A吗?那么,将A放入到线程中,每次执行A都启动一个新的线程,在线程中打开连接,执行处理完毕再关闭联接(其实就是在A中打开和关闭联接),这样就没有任何问题了。
让一组ADO对象依次从头取出数据,处理这个队列。也就是生产者,
消费者问题。