如何让中间层MIDAS/DATASNAP支持大量的并发用户并且控制连接数量

http://www.cnblogs.com/hnxxcxg/archive/2012/02/25/2367488.html

最近在写一个基于XE2 DATASNAP的中间层,以前也写过基于DCOM的MIDAS中间层,看到网上一些同仁对中间层的提问。我摘录俩个典型的提问,如下:

第一个提问:

Midas三层程序,如何支持大量用户同时请求连接?
系统结构: TClientDataSet -> TSocketServer -> scktsrvr.exe -> RemoteDataModule -> ADO
  
  要求:允许500-1000个客户端同时“请求”连接,服务器和客户端均不能死掉。
现状:在现有的程序中,只要同时“请求”连接的客户端达到一个较大的数量,例如80或100,应用服务器就停止响应了。客户端尝试连接时,不但无法建立连接,甚至都无法获得

一个“返回错误”,而是跟着一起停止响应。

期望:能够允许500-1000个客户端同时发出连接请求、尝试连接。当然,可以限制并发工作数,哪怕限制到很小的数量;但是,超出这个数量的客户端在执行

TSocketConnection.Open时,必须能立刻收到一个“连接数已满,拒绝连接”的返回信息;或者进入一个等待队列,重试指定次数或者重试指定时间;或者,哪怕仅仅抛出个异常

。但不允许停止响应,不允许无声无息地死掉。

第二个提问:

基于Midas/Socket/Scktsrvr的三层程序,如何在连接环节限制连接数?
 
架构:TSocketConnection -> scktsrvr.exe -> RemoteDataModule
 
现状:大量客户端(如200个)同时发起连接请求,中间层或scktsrvr明明无法处理这么多的连接,却又不推辞,最终导致客户端、中间层和scktsrvr都死掉。
 
期望:让scktsrvr限制Socket的数量,超过限度(如20个)之后的客户端可以向scktsrvr发出连接请求,但scktsrvr不分配给Socket,拒绝连接;客户端超时之后,弹出对话框提示用户。

网上关于中间层的提问看似千奇百怪,其实集中起来,无非就是上面的俩个大问题(虽然上面的提问都是针对MIDAS的,但同样适合于DATASNAP):

1。让中间层支持大量并发而不会死掉;

2.控制最大的连接数量,防止服务器因硬件资源被耗完而死掉。其实这俩个问题也可以说是等同一个问题。

这俩个问题可以解决吗?答案是能。

首先描述一下许多同仁写中间层的方法:

1. 中间层线程服务方式选择“SESSION”,这也是MIDAS/DATASNAP默认的线程方式,大家往往跟着默认;

2. 在远程数据模块上放一些诸如数据库连接控件、数据集控件。。。。。。

无可否定,这样写中间层是最容易,也是许多教科书中介绍的方式。但正因为这样才导致了上面的问题。

因为这样的方式对服务器端的资源消耗是重量级的:当一个客户端连接上来,服务端对应开一个线程为其服务,直至客户端终止连接才关闭这个线程。为什么说是重量级的呢?当线程开启后,会创建远程数据模块,然后远程数据模块里面的一大堆数据集对象、数据连接对象都会被创建,如此多的对象在客户端的连接周期内一直存在,且只能为一个客户连接提供服务。因为服务器的资源消耗是重量级的,一旦客户连接数量稍微一多,服务器的硬件资源很可能马上就消耗完。此时如果又没有做最大连接数量上限的控制,就只能任由服务器因资源耗尽而当机。这就是这种方式写中间层的弊端。即这种方式决定了中间层能够支持的客户端并发数量是非常有限的,因为每一个客户端对服务端的资源占用都是重量级的:一是占用时间长(客户端只要还保持着连接,服务端资源就一直被占着),二是服务端要创建一大堆对象给每一个客户连接服务。

如何解决?

1. 化重量级对象占用为轻量级占用;2. 化长时间占用为实时占用。

于是对象池呼之欲出,对象池中的对象们能够为所有的客户连接服务,再不是某些对象资源只能为某一个客户连接服务。

最关键的是改变服务端的线程服务方式:不能用默认的"session"线程方式,要改成线程池的方式。对于操作系统来说,能够创建线程的数量总是有限的,比如WINDOWS大概能够创建2000个左右的空线程对象。改为了线程池的方式以后,线程数量再不是限制。

改造成线程池这是第一步,然后改造数据库连接对象池,数据集对象池。。。。。。

这样实现有什么好处?

对象池中的对象只是实时被占用,这个占用只发生在一个客户的一个事件动作发生的那一瞬间,当这个事件一完成,对象即归还对象池中(只是归还池中,并没有释放对象)。对象避免了频繁地创建和释放,减少了许多对象创建所消耗的时间(对象的创建是比较耗时的,何况是如此众多的对象的创建,这要消耗多少时间)。减少了因对象频繁地创建和释放所产生的内存碎片(对象的每一次创建和释放都会产生微量的内存碎片,看似微不足道。但你想过没有:服务器是7*24运行的,且频繁地创建和释放的对象数量是如此众多,这会产生多么大的内存碎片啊。内存碎片一是会影响服务器的执行性能,二个可能使服务器当机)。

如何控制最大的客户连接数量?

设置服务端线程池的上限(PoolSize)吧,控制了线程池最大创建线程的数量,就控制了最大的客户连接数量。

这个上限设置多少合适?

具体要看那台服务器的硬件配置情况了。实际进行压力测试才可得知。

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值