在作DCOM三层结构时,每当一个客户端连接到应用程序服务器时,应用程序服务器的
内存使用和虚拟内存使用都会有所增加,但是当该客户端程序推出并断开连接后,应用程序服务器增长的内存并不能完全释放。最后导致的结果就是应用程序服务器的内存使用和虚拟内存使用不断增加导致虚拟内存不足而死机。
  敢问各位专家,这个问题如何解决。
  以下是对应用程序服务器内存跟踪记录的结果:
      Time              CPU         RAM(内存)  VM(虚拟内存)
2003.04.05  0:40      0:00:00      12,564       6,616
2003.04.05 10:33      0:01:07      16,468      10,316
2003.04.05 16:55      0:02:55      22,000      16,068
2003.04.06  0:37      0:09:13      31,512      25,180
2003.04.06 11:17      0:12:48      36,024      29,776
2003.04.06 15:00      0:14:58      43,520      37,356
2003.04.06 22:41      0:17:41      46,400      40,308
2003.04.07 09:15      0:18:47      50,056      43,732
2003.04.07 13:44      0:21:36      60,884      54,492
2003.04.07 19:18      0:24:36      65,676      59,280
2003.04.07 22:47      0:25:56      66,148      59,772
2003.04.08 09:12      0:27:35      69,420      63,072
2003.04.08 18:11      0:32:57      84,888      78,524
2003.04.08 23:06      0:35:07      89,148      83,072
2003.04.09 08:50      0:36:36      88,876      82,532
2003.04.09 09:54      0:37:46      95,132      88,792
2003.04.09 15:07      0:40:07     101,344      94,969
2003.04.09 22:43      0:43:22     104,152      97,728
2003.04.10 09:27      0:44:46     106,728     100,556
2003.04.10 13:44      0:46:48     115,956     109,568
2003.04.10 20:51      0:49:43     119,904     113,520
2003.04.10 22:55      0:50:39     120,812     114,440
2003.04.11 08:55      0:52:16     121,216     114,756
2003.04.11 13:43      0:54:59     134,456     127,988
2003.04.11 15:57      0:57:03     140,000     133,592
2003.04.11 20:45      0:58:54     138,624     132,080
2003.04.11 22:15      0:59:24     139,376     132,960
2003.04.11 22:29      0:59:27     138,036     131,508

解决方案 »

  1.   

    eastliangliang(青苹果)(道可道,非常道) 
    谢谢,其实在这个应用程序服务器上我没有写一行代码,只是一个最简单的应用程序服务器(包括一个AdoConnection,一个AdoQuery和一个DataSetProvider而已),只是客户端的数量比较庞大。每天陆陆续续的连接达到500左右,但是到了晚上连接的客户端少了,内存和虚拟内存不见释放多少,如此一日一日,最后的结果只有down机了帐。
    还盼望高手能指点迷经,我应该增加一些什么代码才能避免这种情况的发生。
    这其中是不是含有MIDAS的BUG或WINDOWS 2000 SERVER的内存管理BUG呢?唉,目前还不得而知。
    无论如何还是要谢谢青苹果的回复!!!!
      

  2.   

    我们曾经有程序是在VC中用的ADO,每次用完有2K的内存泄漏,我不知他们搞定了没有,明天问问。
    不过你这个不像,一次2K,早就down啦。
      

  3.   

    在DCOM三层结构中,的确存在这种现象,特别是客户端比较多的时候,服务器很容易DOWN机的。要解决这个办法,就要对应用服务器的数据模块的创建进行改进,采用自己的方法去动态创建,使之所有的线程都能为自己所监控,然后每隔一段时间,对所有数据模块实例进行检查,如果没有连接的话,就释放资源。如果要做到更有效率的话,最好使用缓冲池。
      

  4.   

    To wyb716(小刀)
    1、怎样自己创建应用程序服务器中的远程数据模块,在什么消息触发时创建?
    2、怎样监测远程数据模块的连接情况?
    3、怎样释放,在哪里执行释放代码?
    4、能否给段实例性代码,贴出来或MailTo:[email protected]
    谢谢!
      

  5.   

    To wyb716(小刀)
    另外,缓冲池又怎样使用?
      

  6.   

    放心,这样的问题是不存在的,你的列表中还须要一个线程计数,有这个东东就可以计算一下了我的服务器有 17 个 dll 组成, 一般占到 170M 左右内存, ms sql2000 占 300M 内存, 200 个客户机, 全断开后还要占 130M virtual memory, 30M 物理, 但 300 个客户机也不会更大有大的内存占用如果你的线程数量只长不减那就有点问题了呵另外缓冲池 DCOM windows 没有直接支持, try 加一个 RegisterPooled 在 UpdateRegistry
      

  7.   

    对了呵,服务器已经在运行中, 说明你已经有三层的经验了, csdn 上的人还很少
    留个联系方式 MSN:[email protected]
      

  8.   

    那怎么办才好呢?难道没有办法解决吗?
    如果是这样,那么做出来的系统还有什么稳定性可言,三天两头DOWN机,那时候不禁用户要发疯了,我看我也要进精神病院了!唉
      

  9.   

    每次连接后在客户都Free原有的连接及控件行不行?我也不是很懂,只想帮帮你。或许服务器定时刷新一下行不?
      

  10.   

    to xiangding(我是中国人,我爱我的祖国)
      客户端每次都Free了所有自己创建的控件,服务器端并无改善。
      

  11.   

    555555555555555555555555~~~~~~~~~~~~~~~~~~~~~~~~~zzzzzzzzzzzzzzzz
      

  12.   

    客户端关闭时是否没有用代码把CDS关闭?如果频繁的开关远程数据模块的话会出现远程数据模块不能正常关闭的现象,这可能是BUG
      

  13.   

    这是一个很重要的问题,大家在作DCOM三层结构时都会遇到,如果不解决系统将始终存在不稳定的因素,希望高手大力援助,帮忙解决问题
      

  14.   

    定义一个定时回调函数或用一个定时器控件在其OnTimer事件中定时调用WINDOWS API函数 SetProcessWorkingSetSize 具体说明看MSDN
      

  15.   

    谢谢 dolphin2001(抢包山),我先试试,如果能解决,定有重谢!
      

  16.   

    前提是你的程序本身没有什么内存泄漏的问题,这样才可以解决问题。好像开始几次调用那个函数,会返回失败。你可以通过调用GetLastError 来查看你调用结果,用任务管理器查看你的调用的效果。
      
     procedure Test();
     begin
     SetProcessWorkingSetSize(GetCurrentProcess,$FFFF,$FFFF);
     end; SetTimer(Self.Handle,0,5000(间隔时间),@Test);
      

  17.   

    delphi的midas不稳定
    还是每日重启服务器吧
      

  18.   


     上次贴的代码参数存在问题,所以导致经常回收内存失败,
     procedure Test();
     begin
     SetProcessWorkingSetSize(GetCurrentProcess,$FFFF,$FFFF);
     end;修正后的代码
     procedure Test();
     begin
     SetProcessWorkingSetSize(GetCurrentProcess,$FFFFFFFF,$FFFFFFFF); //<<<<
     end;现在可以了,我测试也通过了...
      

  19.   

    你可以换一种连接方式。用deExpress里面的控件吧。比ADO快多了而且很舒服。我一直用它。
      

  20.   

    有现成干吗不用呢。Microsoft有一个工具叫Empty.exe是用来回收特定进程的内存资源。我的QQ2003占了13多MB MEM ,EMPTY 一个只剩不到1MB,,要吗?给我发消息。
      

  21.   

    谢谢hch_45(んこん),请把程序发到信箱:[email protected]
      

  22.   

    to hch_45(んこん)
    也发一份给我吧[email protected].谢谢。
      

  23.   

    这个问题是由于 DCOM 本身的问题。远程模块最好用Sockt连接做服务器这样没有你说的这个问题你可以看看李唯的书,他说的很清楚。这是由于线程的模式不想融合导致的,没有特定的代码可以解决。
      

  24.   

    最近试验了将RemoteDataModole中的ADO控件换成DBExpress,发现在使用的过程中,DBExpress的内存使用情况比ADO的理想,内存的分配和释放都正常,但是DBExperss属于单项的链接,请问各位高手,如何通过DBExpress更新数据库呢?
      

  25.   

    请问shsunb(我怕来不及),怎么才算池化组件呢?
      

  26.   

    唉,这可能是data pooling造成的吧,要是你后台是ms sql倒是可以通过ms sql限制内存用量。
    但如何回收data pooling的内存我就不知道了。
    你的代码可能也会有问题,这很难说啊。
      

  27.   

    to:hch_45(んこん)
      我用Empty.exe试了试,这个程序只能释放内存而不能释放虚拟内存,而且只能运行在Windows 2003上,我现在需要找到释放虚拟内存的方法,还请各位高手解囊相助,小生先谢过了!
      

  28.   

    to overtime(空间在线):
      线程模式为Delphi给出的默认设置;
      

  29.   

    ...
    initialization
      TComponentFactory.Create(ComServer, TRemoteInsert,
        Class_RemoteInsert, ciMultiInstance, tmNeutral);
    end.win2000使用tmNeutral最为高效,可进入公寓内部执行其他不同于当前方法的组件方法,所以应该禁用全局甚至单元级变量。然后安装组件,在激活选项中选择启动对象池即可。还有前几天刚解决COM+的很烦人的数据库锁定问题,现在心情很爽,要不要分,我的有三千多了,呵呵
      

  30.   

    TO:shsunb(我怕来不及)
      我试试,如果能解决问题当重谢
      

  31.   

    TO:shsunb(我怕来不及)
    COM+的的数据库锁定问题是怎样解决的?我也有这个提问。谢谢你!
      

  32.   

    TO:shsunb(我怕来不及)
      以下是线程模式改为tmNeutral后的监测结果,虚拟内存仍然在不断上涨,跟原来的略好一些,请再帮忙分析一下原因,谢谢了!      Time          CPU     RAM      VM    HANDLE
    2003.09.01 14:18  0:02:05  21,200  16,092   305
    2003.09.01 14:31  0:02:10  20,076  14,976   283  
    2003.09.01 14:55  0:02:25  20,412  15,332   272
    2003.09.01 16:50  0:03:33  21,496  16,356   308
    2003.09.01 19:37  0:04:36  22,132  16,960   269  
    2003.09.01 20:51  0:05:12  23,448  18,308   295
    2003.09.02 08:44  0:07:22  25,884  20,576   233  
    2003.09.02 16:12  0:12:45  32,544  27,252   266
    2003.09.02 17:36  0:13:28  32,480  27,216   229
    2003.09.02 17:36  0:15:17  34,268  28,976   251
    2003.09.03 08:39  0:17:34  36,008  30,696   200
    2003.09.03 10:20  0:19:37  46,216  40,948   550
    2003.09.03 13:33  0:21:50  46,640  41,264   375
    2003.09.03 15:01  0:23:23  52,104  46,716   456
      

  33.   

    快点打上Pack!
    你用的是不是MTS?
    使用池化:
    1、组件管理器的具体组件的属性-激活-启动对象池-最小数量
    2、Delphi的TDM的pooled属性
    3、Delphi的TLB编辑器里的CoClass的Flags的Aggregatable
    4、Delphi的TLB编辑器里的CoClass的COM+的
    Call Syn=Requested
    TranMode=Requ A Tran
    Object Pooling=true
      

  34.   

    你取得数据是几天的综合数据,所以除了组件还要考虑win2000有没有运行其他程序。我还有几点建议:
      1)不知你组件端是一个大的组件让客户端直接调用还是按逻辑分成几个小的组件,我建议是后者。
      2)禁止所有的全局变量。对于com+单元,delphi自动生成的窗体变量也要删除,因为调用是通过接口而不是窗体的全局变量。如果存在窗体全局变量在不同线程调用时可能会造成先创建的对象失去引用(因引用指向第二次创建的com+对象地址),从而引起内存泄漏。
      3)不管事务还是非事务组件均要有异常保护,确保最终调用SetComplete或SetAbort
      4)用DUnit或comunit嵌入代码进行测试关于COM+的的数据库锁定问题,我在另外一个贴子里有答复
    http://expert.csdn.net/Expert/topic/2223/2223007.xml?temp=.7945368
    请同时参考其他人的答复,希望你能尽快解决问题程序员本来就是快乐的
      

  35.   

    建议:
    删除所有的全局变量,包括DELPHI自动产生的单元变量
    确保测试环境不受其他程序干扰
    可以使用DUnit、COMUnit进行嵌入测试关于COM+的的数据库锁定问题,看一下我在下面一个贴子里的回答就OK了:
    http://expert.csdn.net/Expert/topic/2223/2223007.xml?temp=.7945368
      

  36.   

    comanche(太可怕) “我的服务器有 17 个 dll 组成, 一般占到 170M 左右内存”也太大了,估计是调试代码造成的将组件卸载删除,组件工程选项中去掉调试功能,重新编译后比较一下大小区别:)
      

  37.   

    to shsunb(我怕来不及) 
      可以使用DUnit、COMUnit进行嵌入测试?
      上述两个东东是什么?
      

  38.   

    还有就是看了一下你的那个三层的帖子,会不会造成内存消耗的原因是因为ado造成的,我建议经server端的ado组件去掉,写一个简单的方法供客户端调用,看看是不是还是消耗掉了内存。
      

  39.   

    会不会是由于ado的资源没有释放的原因?
      

  40.   

    Dunit基本介绍
        Dunit是Xunit家族中的一员,用于Dephi的单元测试。是Extreme Programming测试实现Xtreme Testing的一种工具。Dunit是一个Free的测试工具,没有代码覆盖率功能。
    Dunit的官方Web Site 是https://sourceforge.net/projects/dunit/。
    使用Dunit应该先看看Dunit安装目录下的doc\README.html。
      

  41.   

    我的系统也出现了这样的问题。环境是:客户端+scktsrvr + midas服务器 + ado + oracle.
    我的系统是用bcb6开发的。
    我现在的想法是:将中间层的数据库连接控件的KeepConnection设为false,ado的provider改为微软的试试。
    欢迎各位高手讨论,raptor, comanche等等星星们发表一下高论!
    建议斑竹将该帖置顶