我的若干数据源(有DB、MSMQ、COM、File、FTP、TCP、HTTP、POP3等)都是数组对象实例,有多少种有多少个是由用户设置决定的,而且是不可能用多个队列来处理,因为这部分是负责通讯的,不处理数据,只是收和发,对它来说一切都一样,都是DATA,感谢交流,请给些好的建议

解决方案 »

  1.   

    我认为你没有完全理解我的意思。
    在我的系统里面也有这个问题,也就是端口数量是由用户自己决定,且每个端口的类型也可能不一样,比如A端口也C端口是用a协议通过,B端口用b协议,D端口用c协议,但通过协议是已知的,即我的程序知道有多少种通过协议,我为每一种通讯协议建立了一个队列,处理该协议的程序肯定是确定的。
    用同一种协议的端口只对同一个队列操作。所以队列是确定的,而不是未知的。
    在你的程序里也一样,如果按我的思路处理的话最多也就是8个队列。
    OK?
      

  2.   

    我认为不应该这样作:
    ADO每个连接同时只能开一个事务,而把多个线程的操作作为一个事务是不合理的.或者说,把一个事务分到多个线程中去是不合理的.
    至于性能问题,我觉得可以这样做:
    1.维护一个全局的Connection对象缓冲区,每个线程在缓冲区中寻找空闲的对象使用,并把它标记为非空闲.
    2.如果已经没有空闲的对象,就要创建一个对象.
    3.线程结束时,不释放Connection对象,只是结束事务,并把它所用的对象标为空闲.
    4.缓冲区的大小应该是动态增/减的.
    此外,因为要在不同的线程中使用这些Connection对象,创建它们的线程应该是自由线程,或用CoMarshalInterThreadInterfaceInStream把它们分别列集到一段内存(流)中,在缓冲区中保留这段内存,线程在使用它们时再用CoGetInterfaceAndReleaseStream进行散集.
      

  3.   

    plainsong(轻风):ADO每个连接同时只能开一个事务
     mrzho(mrzhou):我的程序只用了一个连接,且实现了和你一样的目的。
    两位高人显然有不同见解,这一块也是最让我困惑的地方,大家再给解释一下吧!
      

  4.   

    同意 plainsong(轻风) 
    如果可能,为了性能优化,尽量不要使关键的部分串行化。用队列、互斥锁就会导致串行化。最好的办法是维护一个预先初始化的ADO对象池,其中的ADO对象都处于活动状态,这样做允许最大并发的数量等于对象池的大小,根据事务的活动程度选择适当的池容量。如果可能的话,还可以考虑动态调整对象池的策略,以适应峰值流量和空闲期。
    我的全文检索引擎服务器程序就使用了这种办法的线程池响应客户连接,初始值=8,最大峰值=256,持续值=32,空闲时限=8s,只要硬件平台不要太差,高负载的流量毫无问题。
      

  5.   

    不可控问题:
    1.ADOConnection的数量(因为若干数据源对象的数量不定)
    2.数据的数量(峰值和空闲无法感知)
    各位有什么高见再说说
      

  6.   

    关于事务的问题,我再解释一下:
    一般DBMS在处理事务时是以连接为单位的.以ADO为例:当调用ADODB.Connection.CommitTrans,所有用这个连接所作的操作都会被提交;当调用ADODB.Connection.RollbackTrans时所有用这个连接所作的操作都会被放弃.所以,如果几个操作不是一个事务,它们就不应该同时使用一个连接.在串行操作中不存在这个问题,因为大家不会同时使用一个连接,但在多线程时就一定要注意这一点了.
      

  7.   

    不如来一个触发就创建一个处理该触发的实例
    当然,这样的话实例的个数是可控的
    自然,ADO就只有一个啦
    不知这样能不能满足你呢???
    有空的话,请大家看看:
    http://www.csdn.net/expert/topic/745/745893.xml?temp=.265362
      

  8.   

    实际上虽然我的程序是多线程的,但在我的程序里只有一个线程在处理数据,也即只有一个ADO实例,其他线程只管往队列里填数据就行了,剩下的事情交给数据处理线程去处理。这不是很好吗
    我觉得不存在上面所说的那些情况。
      

  9.   

    plainsong(轻风)兄:您的理解有点误会:这个Service是负责通讯的,只管接不管处理,处理是写库之后的事了,所以不必要有ADODB.Connection.CommitTrans和ADODB.Connection.RollbackTrans的考虑,因为数据收到就是收到了,不能回滚,此部分的数据操作就是Insert或Update之类的简单处理,不需要事务,您再给看看,提点什么好的想法
      

  10.   

    plainsong(轻风)兄与 mrzho(mrzhou)兄看法完全不同,看来这真是个困扰大家的问题,大家都来谈谈看法,我现在还是举棋不定,不知怎样处理才是最稳定、最优化的处理方式;我可以提一下,我现在的状况(即一个数据到达进行一次ADO对象的声明--调用--释放)其实也不坏,八种协议N多个实例(另外还有一个发送通讯缓冲重试的触发点)一晚上把ACCESS库(测试用)搞出五万六千多条记录来,很稳定。
      

  11.   

    在客户端超过临界值时可以肯定你现在的方法会受到严峻考验,在客户端(或你的N多个实例)肯定不会超过临界值的情况下,性能方面不会有太大问题,只会有重复建立数据库联接的效率问题;
    如果必须考虑性能,采用plainsong(轻风)和 mrzho(mrzhou)的方案都是可行的,这也是消息、交易中间件中常用的技术,不过目前各厂家的中间件价格较贵,多应用于银行、电信等大的项目中,如果在小型项目中可以考虑COM+的池和MSMQ的队列,如果非要自己做,麻烦其实不小,还需要考虑网络状况、超时等等,反正我现在不会再花工夫去做现成的东西了,研究除外
      

  12.   

    另外,在一个数据库连接中不会同时进行两个交易的,这点不必担心
    mrzho(mrzhou)只用一个数据库连接的技术是正确的,但并不是说只用一个是科学的,一般是采用plainsong(轻风)的池技术,n个数据库连接共享,同时用队列技术管理m个请求,这就要求请求最好是无状态的
      

  13.   

    对于redbirdli(火鸟) 所说"此部分的数据操作就是Insert或Update之类的简单处理,不需要事务",我不太了解具体情况,可能你的情况是不需要的.不过,在Insert和Update操作时需要事务的情况我也是经常遇到的.
    此外,事务的功能不只是把一组操作变成一个元操作,在很多情况下,它还是DBMS管理访问锁的一个单位.比如在这条语句:
    Select * from MyTable Where ID < 50 For Update;
    就会把MyTable中ID<50的所有记录锁住,不允许其它连接对这些记录进行修改操作,直到该事务结束.这种功能在UPDATE操作中很有用.
      

  14.   

    如果不需要事务的话,是可以在多个线程中用同一个ADODB.Connection的.因为ADODB.Connection的线程模式是Apartment,这就是说,这个对象可以安全地被多个线程调用,它自己会把多个线程对它的调用排队,在一个线程中执行.不过速度有可能会比每个线程用一个Connection慢一些(如果不考虑数据库连接时间).因为我们主要操作是通过Command或Recordset完成的,而它们对Connection的调用究竟频繁到什么程度,我是不清楚的,所以也无法分析到底会慢多少.
    如果使用连接池的方法,数据库连接时间的影响基本上解决了,这样应该要比用一个连接快一些(也可能快的有限),不过程序就复杂很多了.
      

  15.   

    如果数据存储很快而接收数据很慢也可以用mrzho(mrzhou)的这种方式:
    用几个线程负责接收数据,一个线程负责把接收到的数据入库,这种方式好象叫生产者-消费者模式.如果入库的速度跟不上,可以增加几个线程进行入库(增加消费者,也算是响应国家的"刺激消费"的号召吧).
      

  16.   

    我认为plainsong(轻风)的设计服务程序的负载性会比较好,但是数据库的压力不小
      

  17.   

    关于构建池的最简单的方法也是最好的方法就是这3个API函数
    CreateIoCompletionPort
    GetQueuedCompletionStatus
    PostQueuedCompletionStatus另外Delphi6运行库的
    ISAPIThreadPool.pas 有完整的线程池实现代码 在\source\internet\
      

  18.   

    我记得李维的书中介绍了 无状态com,不知道是不是和这个有关
         学习先
      

  19.   

    如果你项目时间比较宽裕的话,可以考虑用完成端口模型,在处理线程开始处建立连接,结尾处释放连接。
    至于"数据库的连接断开对性能影响",可以不用考虑,SQL有连接池的
      

  20.   

    I would say connection pool. Besides dynamic resizing the pool, you can allow administrator to configure the upper limit and lower limit. So the system will at least have some connection available in the pool. And when there are too many clients concurrently, the upper limit will protect the database from being too busy.In case you run out of connection (reach the upper limit), you still need a queue or something to let the requesting clients wait.
    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.
      

  21.   

    and if you configure it as "no upper limit", it is equivalent to plainsong(轻风)'s way.
      

  22.   

    dont use ADO, direct connect to database
      

  23.   

    可能是我水平不够吧,上面大多数的发言我都看不懂(不知道发言者是否真的做过?),不过我觉得完全没有这么复杂。
    我也做过类似的SERVICE,你所说的两个问题
    1.有N条数据到达就要有N个ADO对象实例和对同一数据源的N个连接
    连接是限制的,达到一定的数目时肯定出错,所以这种方案在流量不大时可取,但如果流量很大肯定会出现问题,不是很好的解决方案。
    2.数据高峰时,频繁的进行对象的创建释放、数据库的连接断开对性能影响很大
    确实值得考虑,对象的创建和连接的建立对性能影响确实很大。完全可以创建一个全局的连接对象(但这个对象是否始终保持联接则要考虑了),你的数据处理不是都要调用A吗?那么,将A放入到线程中,每次执行A都启动一个新的线程,在线程中打开连接,执行处理完毕再关闭联接(其实就是在A中打开和关闭联接),这样就没有任何问题了。
      

  24.   

    建议最好串行化,稳定最为关键。把到达的数据全部插入队列。然后
    让一组ADO对象依次从头取出数据,处理这个队列。也就是生产者,
    消费者问题。