Midas三层程序,如何支持大量用户同时请求连接?(300)

  • 主题发起人 fatalexception
  • 开始时间
F

fatalexception

Unregistered / Unconfirmed
GUEST, unregistred user!
    系统结构: TClientDataSet -> TSocketServer -> scktsrvr.exe -> RemoteDataModule -> ADO    要求:允许500-1000个客户端同时“请求”连接,服务器和客户端均不能死掉。    注意:不需要这些用户同时“成功建立”连接、“保持”连接,更不需要同时操作数据。    现状:在现有的程序中,只要同时“请求”连接的客户端达到一个较大的数量,例如80或100,应用服务器就停止响应了。客户端尝试连接时,不但无法建立连接,甚至都无法获得一个“返回错误”,而是跟着一起停止响应。    期望:能够允许500-1000个客户端同时发出连接请求、尝试连接。当然,可以限制并发工作数,哪怕限制到很小的数量;但是,超出这个数量的客户端在执行TSocketConnection.Open时,必须能立刻收到一个“连接数已满,拒绝连接”的返回信息;或者进入一个等待队列,重试指定次数或者重试指定时间;或者,哪怕仅仅抛出个异常。但不允许停止响应,不允许无声无息地死掉。    通俗地讲,我不要求你SocketServer多么神通广大、接纳几百几千用户同时保持连接、操作数据。你可以只有很小的负载能力,哪怕只能同时容纳20个客户端保持连接、操作数据。但是,当第21个客户端试图连接时,你必须立刻告诉客户端“满了,不再提供连接了”,以便客户端另做安排,比如等几秒后重试,或者让用户自己决定是否重试。你不能自己大包大揽,不管来多少连接请求都通吃,但又无法连接成功或者无法完成数据请求,最后把自己搞死,把应用服务器搞死,让我的客户端傻等着。    请问,可否实现?如何实现?可少量改写scktsrvr.exe,但不能另写socket程序或对scktsrvr.exe进行大篇幅的重写。  
 
除非自己管理用户在线数量,到达你要求的数量后就不给进来。 要不就自己动手写一个适合自己的应用服务。
 
constructor TSocketDispatcher.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
ServerType := stThreadBlocking;
OnGetThread := GetThread;
OnGetSocket := GetSocket;
OnClientError :=do
ClientError;
end;
procedure TSocketDispatcher.GetSocket(Sender: TObject;
Socket: TSocket;
var ClientSocket: TServerClientWinSocket);
begin
// 限制连接为20, >=则新连接断开 if Self.Socket.ActiveConnections >= 20 then
begin
Winsock.closesocket(Socket);
abort;
end;
end;
procedure TSocketDispatcher.DoClientError(Sender: TObject;
Socket: TCustomWinSocket;
ErrorEvent: TErrorEvent;
var ErrCode: Integer);
begin
if (ErrorEvent = eeDisconnect) and Socket.Connected then
begin
// 这里就是为啥断了,还在线,在列表里面 Socket.Disconnect(Socket.SocketHandle);
//PostMessage(Socket.Handle, CM_DEFERFREE, 0, 0);
end;
ErrCode := 0;
end;
 
停止响应,一般来说原因可能很多,如果是scktsrvr的原因,一般也是因为创建线程太多,引起线程切换太慢,或者因为对应的COM组件的操作太费时啥的一般来说一个进程,可创建的线程应当不止100,我试过空线程,创建个2000左右就不行了,不说2000,1000个是没问题的,所以,你应该检查你的COM服务是否有哪些是很费时的操作,这样,检查才有意义。你拿这个程序试试,代替scktsrvr,然后检查里面的哪些函数调用很费时,然后相应作优化吧:http://www.delphibbs.com/keylife/iblog_show.asp?xid=36085
 
呵呵,scktsrvr.exe能支持500-1000个连接吗?这么大并发,还是换一套架构吧,如果有任何可能的话。
 
to copy_paste: 谢谢!但仍然不能解决问题。 跟踪发现,程序根本不会执行到DoClientError里面,就直接死住了。
 
to xianjun:  我觉得我已经写得很清楚了,在三个地方特意澄清了,可能还是写得不够清楚吧。 那就再澄清第四遍:是要允许1000个用户同时发起连接请求,而不是要允许1000个用户同时连接成功。允许失败,允许弹出异常,允许返回错误代码,但不允许失去响应。
 
我不写MIDAS,我只不过熟悉scktsrvr的程序,写着玩的,具体问题你要自己弄。我这人比较懒,不好意思。或者你试试我写的那个程序代替scktsrvr,看看有没问题,我写那程序丢在那边也是这意思,测试一下有哪些BUG,看看能不能用,我当时也是为了给我朋友一个可分析的工具而已。
 
在这个运行模式下,如果windows 系统连接线程数超过200, 效率将大幅度下降, windows将大量工作时间应付连接线程的上下文切换. 随着连接的增加,cpu占用率将快速增长.不知你 服务端的 thread cache 设置的是多少?
 
在这种结构下,客户端连接服务端成功后,服务端会建立线程实例,如果你的服务端连接80或接100都没有问题,而连接101个时就死了(卡住了),是否是服务器硬件性能负载不了,或thread cacae设得太小? 可以参考自带的scktsrvr程序,里面有当前连接客户数功能。
 
to xiaobb:  关键是希望由我自己来限制连接数,而不是任由监听程序、中间层程序、服务器软硬件环境被耗死。Delphi封装的Socket好像是必须先建立连接,服务器不可以拒绝建立连接,这一点很恼人。
 
这个不懂,帮顶。。。
 
顶部