全國最多中醫師線上諮詢網站-台灣中醫網
發文 回覆 瀏覽次數:2391
推到 Plurk!
推到 Facebook!

請教一下斑竹,關於應用服務器內存佔用比較高的問題

答題得分者是:pcplayer99
qinmingzsj
一般會員


發表:9
回覆:12
積分:4
註冊:2003-05-08

發送簡訊給我
#1 引用回覆 回覆 發表時間:2006-07-11 12:06:40 IP:59.37.xxx.xxx 未訂閱

請教一下斑竹,關於應用服務器內存佔用比較高的問題

我使用DELPHI6開發了一個關於三層的C/S企業應用程式,但是根據多日的觀察,發現應用服務器的內存一天一天的增加,因此想請教一下老師針對我的程式是否有好的解決方案.

我具體的架構以及主要的程式如下:
應用服務器:
一: 針對主TRemoteDataModule
1. 主TRemoteDataModule模塊(DM_SERVER),為了將數據庫的連接統一我在DM_SERVER使用了一個TADOConnection (adoCN_Server)
2. 在DM_SERVER中我定義了一個屬性(Connection)以代表adoCN_Server提供給子TRemoteDataModule模塊
具體調用程式:
function TDM_SERVER.Get_Connection: Integer;
begin
Result := Integer(adoCN_Server);
end;
3. 在在DM_SERVER中我定義了10個屬性代表10個子TRemoteDataModule提供給客戶端
具體程式(只力例舉了一個):
function TDM_SERVER.Get_PQIN_GSD_PACKRM: IQIN_GSD_PACKRM;
begin
Result := FQIN_GSD_PACKRM.CreateComObject(nil) as IQIN_GSD_PACKRM;
Result.MainRm := self;
Result.Connection := Get_Connection;
end;
4 我定義了一個了被其他子TRemoteDataModule繼承的介面IBASE_RM,在其中我又定義了幾個屬性: MainRm(Read/Write) 取得TRemoteDataModule模塊(DM_SERVER)
Connection 取得TRemoteDataModule模塊(DM_SERVER)中的數據庫的連接
5 我定義了10個 子TRemoteDataModule(繼承了IBASE_RM) 在10個 子TRemoteDataModule中我做了如下動作:
(只力例舉了一個):
5.1
var
FQIN_GSD_PACKRM: TComponentFactory;
作為主TRemoteDataModule獲取子TRemoteDataModule全局變量
5.2
function TQIN_GSD_PACKRM.Get_MainRm: IDM_SERVER;
begin
Result := FMainDM
end; //取得TRemoteDataModule模塊(DM_SERVER)
procedure TQIN_GSD_PACKRM.Set_MainRm(const Value: IDM_SERVER);
begin
FMainDM := Value;
end;
procedure TQIN_GSD_PACKRM.Set_Connection(Value: Integer);取得數據庫連接
var
Icount: integer;
begin
FCon := Value;
for Icount := 0 to ComponentCount - 1 do
begin
if Components[Icount] is TCustomADODataSet then
TCustomADODataSet(Components[Icount]).Connection := TADOConnection(Value);
end;
end;
10個 子TRemoteDataModule中定義了其他業務邏輯(省略),以及(TADODataSet組件.和相應的DataSetProvider組件)

客戶端:
一: 針對客戶端的TDataModule(COMMEM_DM)
1. 在COMMEM_DM中我加入了一個TSocketConnection(ScC_COMMEM_DM) ,一個TSimpleObjectBroker(SOBroker)以及10個TSharedConnection
2. TSocketConnection(ScC_COMMEM_DM)連接SERVER(SERVER.DM_SERVER)以及SOBroker
3. 10個TSharedConnection的Parentconnection連接ScC_COMMEM_DM, ChileNmae分別連接10個不同的介面.
4. 我另外加入了10個不同的TDataModule,在其中加入了相應的TClientDataSet組件
5. 客戶現在只有16個模塊使用.
問題:
1. 客戶端少的時候沒有發現任何問題.
2. 當我的客戶端超過60多個達到150的時候我觀察到應用服務器的EXE文件所佔用的記憶體達到200-400多MB
3. 當我不關閉應用服務器, 應用服務器的EXE文件所佔用的記憶體每天以100多MB的速度增加
4. 而且當我用三台客戶端測試的時候,我發現如果我退出兩個客戶端,只要有一個客戶端連接.先前的應用服務器的EXE文件所佔用的記憶體並沒有釋放,是不是在應用服務器客戶端連接的那些子遠程數據模塊沒有釋放呢?
5. 因為整個項目中有200多個模塊,客戶端有200多台,如果照這樣的話,我的應用服務器豈不很快就會崩潰.
6. 數據庫方面應該不用考慮,因為我以前的兩層用此沒有問題.
是不是我的架構設計有問題,還是其他方面沒有考慮到? 敬請斑竹解答我的這個困惑,不甚感激

注明,我在論壇查找過類似此的貼子,但是我按照某些方法還是沒有解決問題.

pcplayer99
尊榮會員


發表:146
回覆:790
積分:632
註冊:2003-01-21

發送簡訊給我
#2 引用回覆 回覆 發表時間:2006-07-12 00:35:02 IP:218.18.xxx.xxx 未訂閱
我猜你的架构是这样:

DataBase <--- ADOConnection <----- ADODataSet <---- xxxx xxxx <--- ClientDataSet

如果是这样,当你的客户端一直向服务器端提交数据,你的 ADODataSet 里的数据会越来越多,当然你的服务器端的 EXE 占用的 RAM 就越来越大。

如果是这样,试一下在半夜没有客户端连接的时候,让服务器端的所有 ADODataSet 都 Close 一下,甚至让 ADOConnection 也 close 一下。
pcplayer99
尊榮會員


發表:146
回覆:790
積分:632
註冊:2003-01-21

發送簡訊給我
#3 引用回覆 回覆 發表時間:2006-07-12 00:39:49 IP:218.18.xxx.xxx 未訂閱

===================引 用 文 章===================


5. 因為整個項目中有200多個模塊,客戶端有200多台,如果照這樣的話,我的應用服務器豈不很快就會崩潰.
6. 數據庫方面應該不用考慮,因為我以前的兩層用此沒有問題.
是不是我的架構設計有問題,還是其他方面沒有考慮到? 敬請斑竹解答我的這個困惑,不甚感激

注明,我在論壇查找過類似此的貼子,但是我按照某些方法還是沒有解決問題.

------------------------------


另外,如果你有 200 个客户端,可能你不能用 TRemoteDataModule 来做 N-tier 了,要考虑使用 COM 了。使用COM ,使用无状态对象,才能解决你的问题。


就算使用普通的 COM 模式的 N-tier,客户端也必须采用无状态模式,在从服务器端获取数据后就断开和服务器端的连接,在需要提交数据给服务器端的时候才再次建立连接。这样,真正在同一时间连接服务器端的客户端的数量就没有那么多了。
qinmingzsj
一般會員


發表:9
回覆:12
積分:4
註冊:2003-05-08

發送簡訊給我
#4 引用回覆 回覆 發表時間:2006-07-12 10:26:48 IP:59.37.xxx.xxx 未訂閱

TO:pcplayer99

我猜你的架构是这样:

DataBase <--- ADOConnection <----- ADODataSet <---- xxxx xxxx <--- ClientDataSet

如果是这样,当你的客户端一直向服务器端提交数据,你的 ADODataSet 里的数据会越来越多,当然你的服务器端的 EXE 占用的 RAM 就越来越大。

如果是这样,试一下在半夜没有客户端连接的时候,让服务器端的所有 ADODataSet 都 Close 一下,甚至让 ADOConnection 也 close 一下。

你說的沒錯,我的架構是這樣,但是我在客戶端每次使用ClientDataSet獲得數據后,服務端的ADODataSet就已經自動關閉了因為我的應用服务器本身就是個無狀態的.這個我已經通過測試沒有問題.但是內存還是不停的增長,我懷疑是不是Result := FQIN_GSD_PACKRM.CreateComObject(nil) as IQIN_GSD_PACKRM;生成的物件沒有釋放,可是我不知道應該在哪里去釋放它!

懇請各位先進在幫我想想辦法


qinmingzsj
一般會員


發表:9
回覆:12
積分:4
註冊:2003-05-08

發送簡訊給我
#5 引用回覆 回覆 發表時間:2006-07-12 10:32:23 IP:59.37.xxx.xxx 未訂閱



===================引 用 文 章===================


5. 因為整個項目中有200多個模塊,客戶端有200多台,如果照這樣的話,我的應用服務器豈不很快就會崩潰.
6. 數據庫方面應該不用考慮,因為我以前的兩層用此沒有問題.
是不是我的架構設計有問題,還是其他方面沒有考慮到? 敬請斑竹解答我的這個困惑,不甚感激

注明,我在論壇查找過類似此的貼子,但是我按照某些方法還是沒有解決問題.

------------------------------


另外,如果你有 200 个客户端,可能你不能用 TRemoteDataModule 来做 N-tier 了,要考虑使用 COM 了。使用COM ,使用无状态对象,才能解决你的问题。


就算使用普通的 COM 模式的 N-tier,客户端也必须采用无状态模式,在从服务器端获取数据后就断开和服务器端的连接,在需要提交数据给服务器端的时候才再次建立连接。这样,真正在同一时间连接服务器端的客户端的数量就没有那么多了。

因為架構已經確定,而且有許多成功的商業應用都是使用 TRemoteDataModule ,我想這個應該不是問題,在客戶端我使用的ClientDataSet的FetchOnDemand使得應用服務器是无状态对象,所以原理就是在从服务器端获取数据后就断开和服务器端的连接,在需要提交数据给服务器端的时候才再次建立连接.

不知道我的這個想法是不是不正確,盼請再次援助!!

pcplayer99
尊榮會員


發表:146
回覆:790
積分:632
註冊:2003-01-21

發送簡訊給我
#6 引用回覆 回覆 發表時間:2006-07-12 11:53:12 IP:219.134.xxx.xxx 未訂閱

===================引 用 文 章===================



===================引 用 文 章===================


5. 因為整個項目中有200多個模塊,客戶端有200多台,如果照這樣的話,我的應用服務器豈不很快就會崩潰.
6. 數據庫方面應該不用考慮,因為我以前的兩層用此沒有問題.
是不是我的架構設計有問題,還是其他方面沒有考慮到? 敬請斑竹解答我的這個困惑,不甚感激

注明,我在論壇查找過類似此的貼子,但是我按照某些方法還是沒有解決問題.

------------------------------


另外,如果你有 200 个客户端,可能你不能用 TRemoteDataModule 来做 N-tier 了,要考虑使用 COM 了。使用COM ,使用无状态对象,才能解决你的问题。


就算使用普通的 COM 模式的 N-tier,客户端也必须采用无状态模式,在从服务器端获取数据后就断开和服务器端的连接,在需要提交数据给服务器端的时候才再次建立连接。这样,真正在同一时间连接服务器端的客户端的数量就没有那么多了。

因為架構已經確定,而且有許多成功的商業應用都是使用 TRemoteDataModule ,我想這個應該不是問題,在客戶端我使用的ClientDataSet的FetchOnDemand使得應用服務器是无状态对象,所以原理就是在从服务器端获取数据后就断开和服务器端的连接,在需要提交数据给服务器端的时候才再次建立连接.

不知道我的這個想法是不是不正確,盼請再次援助!!


-------------------------------------------------------


假设你的客户端是用 DCOMConnection 连接服务器端,通常情况下,一个 DCOMConnection 连接,服务器端就会生成一个对应的 TRemoteDataModule 实例,也就要占用相应的记忆体空间。所以,不单是你的 ClientDataSet 使用无状态,而是要让你的 DCOMConnection 的连接关掉,服务器端才会释放那个 TRemoteDataModule 实例。


如果客户端频繁地连接/关掉连接,服务器端就会频繁地 Create 那个 TRemoteDataModule 的实例,则会导致 CPU 拼命跑,也就是说,节约了记忆体空间,但浪费了 CPU 时间。在这样的情况下,如果采用 COM ,并且把 COM 设定位使用 Pool,那么,一个COM 的 TTransactional Data Module(类似一个 TRemoteDataModule)在被 Create 后,当客户端释放连接的时候,它会被放进 Pool 里,而不是被立即释放。另一个客户端连接过来的时候,这个 DataModule 可以去服务它了。这样,同时服务200个客户端,可能只需要在服务器端同时又5个DataModule的实例就够了。

当然,使用 TRemoteDataModule 也可以有 Pool,自己要写一点代码来实现,而不是象 COM 由WINDOWS 系统来实现POOL。这个 POOL,DELPHI 带的 DEMO 里,有例子,你可以参考。

qinmingzsj
一般會員


發表:9
回覆:12
積分:4
註冊:2003-05-08

發送簡訊給我
#7 引用回覆 回覆 發表時間:2006-07-26 18:00:05 IP:59.37.xxx.xxx 未訂閱

===================引 用 文 章===================

当然,使用 TRemoteDataModule 也可以有 Pool,自己要写一点代码来实现,而不是象 COM 由WINDOWS 系统来实现POOL。这个 POOL,DELPHI 带的 DEMO 里,有例子,你可以参考。

我查看了 DELPHI 带的 DEMO ,但是它所生成的POOLER卻不能用TSocketconnection 連接,只能用Dcomconnection連接,但是當我的客戶端不在APPSERVER所在的電腦上時卻提示"類別未登錄"(我用dcomcnfg卻看不到這個SERVER.POOLER),所以再次請求幫助.

1. 它所生成的POOLER怎樣才能用TSocketconnection 連接

2. 提示"類別未登錄"該怎么辦.

甚盼回答,非常感激

系統時間:2024-04-20 22:12:49
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!