讨论:如果服务器需要承受1000个以上的并发,你同意使用线程阻塞式还是非阻塞式?(300分)

B

barton

Unregistered / Unconfirmed
GUEST, unregistred user!
我的服务器马上需要提交测试了。可是到最后有个VC++程序员告诉我:不能用线程阻塞式,
因为这意味着1000个用户连接需要开1000个线程,而这么多线程服务器怎么能够承受!是
啊!我从前写个七八个服务器最多的时候也只有20多个并发连接,一点速度上的问题都没
有。这几天头脑里都是线程、线程、线程:(
服务器线程阻塞式的理由:支持多CPU和CPU的超线程性能;对连接响应快;方便连接管理。
你看看sconnect.pas、mconnect.pas、scktmain.pas,你就会发现,Borland在关键的时候
都用线程阻塞,一定有他的道理。
服务器非阻塞式的理由:线程少,易于调试和维护,CPU负荷轻。那位VC++程序员似乎一口
咬定线程阻塞式不能用于太多连接的服务器。

我的系统核心需要占用2-3个线程,一个主线程,一个维护线程,一个运行线程,处于维护
状态的时候只有两个线程,运行状态的时候三个线程。当然,如果有用户连接,每个连接
相应增加一个线程。线程间的同步没有问题,都是通过消息和队列管理来实现的,保证线
程间不会发生冲突。除主线程外,每个线程大多数情况下都处在wait函数中。

同意或反对线程阻塞式的都请举起你们高贵的手来,如果能说出点经验之谈,另有高分相
赠!
 
严重关注此题
 
随便点点就能拾分的问题居然没有人回答:(
张无忌哪去了?
爱元元的哥哥哪去了?
算了,我已经放弃了,决定使用完成端口模型。
 
当然用完成端口了,到www.playicq.com去找到softdog的哪个控件就可以开始写了
 
我感觉,[red]破机器就别用来做服务器![/red]
记得某期的程序员上面讲过,印度程序员就是这样干的,
既然你那是服务器,一定配置好,就开了个 20M 的静态
数组。

所以,我同意用阻塞式!
 
同意张无忌的看法,用完成端口是唯一的途径。线程池模式比较适合做代理服务器,中小型WEB
服务器这种无需长时间连接的事务。不过完成端口可能是windows下最复杂的tcp/ip工作模式,
要好好读读相关资料才可以。
 
to 张无忌:
终于把你给唤出来了。
softdog的控件我down下来看了,基本上没有什么用。它的事件都是基于一个Overlapped结
构,而不是Delphi常用的对象。如果要发送或接收的数据包的长度大于overlapped结构最大
的缓冲区,显然有拆分和整合的过程。既然写成VCL应该封装这些方法。
此外,Accept和Worker使用两类线程似乎不合适。这样系统默认为10个线程,而有的VC++
源码中没有Accept线程或者最多一个Accept线程。
在建立IoCompletionPort的时候有个CompletionKey参数,连接VCL中的对象似乎是一个很好
的选择,但该控件中没有使用。
 
to blueky:
你的说法有点太绝,“唯一”途径不太确切。其实即使不用完成端口也可以使用非阻塞模式
或者复杂一点用重叠模型。对于操作系统来说,完成端口模型确实很复杂,但从调用者的角
度看,我并没有发现完成端口模型比线程阻塞模式复杂呀。只是因为不能通用(仅支持
WindowsNT/2000),不受其它厂家推荐才显得有点神秘。完成端口模型也并不是在WinSocket
中才有,有些文件访问过程也采用这种模型的。
我想Borland的MIDAS/DataSnap不支持完成端口的原因可能是因为无法在Kylix中实现吧?
 
请张无忌继续发言,我会另开一贴给你300分。
 
其实完成端口会自动把所有的连接排队,按一定的规则进行处理,所以少量线程就足够了,
你如果写一个小ECHO例子的话,仔细观察就会发现他是一线程可以同时处理很多连接,
线程越少,线程之间切换的开销就越小,适合处理大量的连接,CompletionKey一般是放
TSocket类型,而客户套接字的一些属性则放到哪个LPWSAOverlapped后面,在服务器类的
开发中越少用对象效率就越高,因为对象的开销很大,所以很多都是用指针和结构来取代
对象,提高效率。
我最近写过一个重叠I/O的东东,一个线程就可以提供多个并发请求,只是没有经过大量
连接的测试,具用过这中方式的朋友说可以同时处理10000多个连接...
 
在服务器上一个程序可以承受2000多个线程,没有问题的,我们去年测试过,但对机器要求可是挺高的
 
在大量连接时,线程阻塞方式的确效率不高,我正在做一个ECHO测试,用INDY的ECHOSERVER,
本机开客户端(单线程管理多CLIENT)和SERVER,在10-200个连接时,收发都能达到4、5MBYTE/S,
CPU占用率很低,但是到了1000个连接时,SERVER的占用率达到了35%,系统处理TCP的开销达到
35%左右,客户端才是十几%,流量也只能达到1、2MBYTE/S(还是收发加起来)。
 
To barton: “唯一”一词是针对大规模的同时连接事务处理而言,你用重叠IO,用线程池,勉强实现,
但是想稳定工作就没那么简单了。 微软的IIS就是采用完成端口的,所以他的效率就是比apache
for windows高。 一台机开2000个线程不是不可以,但是那样子的话CPU需要花很多的时间在处理
线程切换,调度上面,产生很大的额外开销,所以说他不适合。
事实上,如果你反编译一下传奇的服务器端程序就可以发现,他甚至只用delphi的TCPSERVER标准控件
的非阻塞模式来实现服务器。从技术上说他们的程序不怎么样,但是能达到目的,创造这么大的价值,
就行了。
 
想想IIS用了什么?为什么不能在win 9X上运行?完成端口?[:D][:D]
 
to bluely:
搞技术工作的应该严谨。在这里“唯一”就意味着没有别的选择。既然有别的选择就不能
叫“唯一”。我无意和你抬杠。如果你说成“最佳”可能更合适一些。线程太多需要服务
器不断切换场景不错,但重叠IO不能稳定工作的说法没有依据。只是因为通过事件实现仍
然是阻塞模式,服务器的性能得不到更好的发挥。事实上在非NT/2000平台上,重叠可能是
替代完成端口的最好的选择。你是否知道PWS用什么IO模型?
 
to gxcooo:
看看Windows SDK帮助:
CreateIoCompletionPort:
Windows NT: Yes
Win9x: No
Win32s: No
 
传奇服务器用非阻塞模式的TCPServer?我不知道。非阻塞模式的TCPServer只需要一个CPU就
行了,那如果服务器用4个CPU,另外三个岂不是闲着?现在能做游戏服务器的机器最少也得有
4个CPU吧?
 
我的服务器运行在一个双CPU的机器上。其实我估计我的服务器最多也就200-300个连接。我
想线程阻塞模式应该足够。但作为探讨的话,这个课题很有意思。
张无忌、wingerk、beta、bulely、ghb1974的发言给了我很大的启示,先谢谢。等本贴结束
的时候我来发表综述。
请继续!
 
重叠I/O也可以处理大量连接,用一个线程也可以处理很多连接,只要处理的好,也没有什么
问题,而且在98下可以正常使用。。。估计PWS就是用重叠I/O的。。。
 
顶部