关于"登陆服务器"的架构设计

已查看 38 次
跳至第一个未读帖子

关中刀客

未读,
2007年5月24日 02:40:502007/5/24
收件人 高性能网络编程邮件列表、请教,讨论
大家好:
最近在设计这个"登陆服务器"。设计了几个方案都感觉缺陷很大。这个"登陆服务器"主要的职责是接受客户端的登陆请教(帐号+密码)。然后发
给"数据库服务器"验证,如果数据库里面有的话,"数据库服务器"发包(包括这个用户的具体信息)给"登陆服务器",然后"登陆服务器"把这个信息发给
一个"大厅服务器",然后把这个"大厅服务器"的port 和IP发回给客户端,客户端在区连接"大厅服务器".............

为了同时可容纳很多的人"登陆",我在"登陆服务器"中使用IOCP连接和接受客户端请求,单独开一个线程接受"数据库服务器"的数据,同
时又有几个socket连接着"大厅服务器"。
现在的问题就是:在这个"完成端口"的线程池处理函数中,只需要recv一次客户端的信息。而我每次有客户端连接的时候。都要new全局的"句
柄结构"和"数据结构体",把它和IOCP连接起来。等受到了消息后,就通过和"数据库服务器连接的socket"法给"服务器服务器"。这样子,我感
觉没有合理的运用iocp,并贴会new很多的"结构体",然后只能在返回给客户端消息后delete .这样子程序很快就没空间可分配了,尽管我只用
了"对象池"
请大家根据自己的经验指点一下,谢谢.

sunway

未读,
2007年5月24日 02:50:092007/5/24
收件人 高性能网络编程邮件列表
系统的new delete很快的,你只要限制一下同时登陆数和接受数据间隔,没那么容易用光内存的。
这个问题网络上大把的例子,建议你先去CodeProject上找代码看看。

qiaojie

未读,
2007年5月24日 04:37:022007/5/24
收件人 dev4s...@googlegroups.com
这种应用没必要用什么IOCP,徒增编程复杂度。你的问题是没有做拥塞控制,接受连接的吞吐量超过了后端数据库IO的吞吐量,导致一段时间以后累积了很多后端来不及处理的连接,你又不控制拥塞导致内存耗尽。其实用非阻塞的select轮询就足够了,网络层自动的帮你做了拥塞控制从而简化了编程。


 
在07-5-24,关中刀客 <guanzho...@gmail.com > 写道:

sunway

未读,
2007年5月24日 05:23:572007/5/24
收件人 高性能网络编程邮件列表
个人感觉登陆服务器有必要用完成端口或者EPOLL,
1.因为登陆服务器是并发连接多.
2.单连接通讯数据量小。
3.用户不介意等个几秒。
我做过的loginserver并发连接都比较高,经常5k并发连接以上。
我一般的做法是前面2*CPU个数的iocp线程,后面8~12个db线程。基本上够用了。

On May 24, 4:37 pm, qiaojie <qiao...@gmail.com> wrote:
> 这种应用没必要用什么IOCP,徒增编程复杂度。你的问题是没有做拥塞控制,接受连接的吞吐量超过了后端数据库IO的吞吐量,导致一段时间以后累积了很多后端来 不及处理的连接,你又不控制拥塞导致内存耗尽。其实用非阻塞的select轮询就足够了,网络层自动的帮你做了拥塞控制从而简化了编程。
>
> 在07-5-24,关中刀客 <guanzhongda...@gmail.com> 写道:


>
>
>
>
>
> > 大家好:
> > 最近在设计这个"登陆服务器"。设计了几个方案都感觉缺陷很大。这个"登陆服务器"主要的职责是接受客户端的登陆请教(帐号+密码)。然后发
> > 给"数据库服务器"验证,如果数据库里面有的话,"数据库服务器"发包(包括这个用户的具体信息)给"登陆服务器",然后"登陆服务器"把这个信息发给
> > 一个"大厅服务器",然后把这个"大厅服务器"的port 和IP发回给客户端,客户端在区连接"大厅服务器".............
>
> > 为了同时可容纳很多的人"登陆",我在"登陆服务器"中使用IOCP连接和接受客户端请求,单独开一个线程接受"数据库服务器"的数据,同
> > 时又有几个socket连接着"大厅服务器"。
> > 现在的问题就是:在这个"完成端口"的线程池处理函数中,只需要recv一次客户端的信息。而我每次有客户端连接的时候。都要new全局的"句
> > 柄结构"和"数据结构体",把它和IOCP连接起来。等受到了消息后,就通过和"数据库服务器连接的socket"法给"服务器服务器"。这样子,我感
> > 觉没有合理的运用iocp,并贴会new很多的"结构体",然后只能在返回给客户端消息后delete .这样子程序很快就没空间可分配了,尽管我只用
> > 了"对象池"

> > 请大家根据自己的经验指点一下,谢谢.- Hide quoted text -
>
> - Show quoted text -

关中刀客

未读,
2007年5月24日 06:35:182007/5/24
收件人 高性能网络编程邮件列表
我感觉要处理同时连接很多个请求的话,用IOCP是绝对合理的
select好像在windows平台上很少用,因为效率很低,浪费cpu

> > - Show quoted text -- 隐藏被引用文字 -
>
> - 显示引用的文字 -

qiaojie

未读,
2007年5月24日 08:13:392007/5/24
收件人 dev4s...@googlegroups.com
并发连接数意义不大,主要看你的每秒最大能处理的登陆请求数,如果你的后端最大每秒只能处理3000个请求,而你接受10000多个连接在用户层就没什么意义,还不如缓冲在网络层,网络层缓冲满了系统就开始拒绝连接,这可以防止风暴连接的时候把服务器压垮。
至于登陆服务器用select毫无问题,因为都是短时的连接,一般你select的时候大多数情况数据已经可读,不存在大量idle connection的情况,用iocp不会有什么性能上的优势。
 
 
 
 
在07-5-24,sunway <sunh...@gmail.com> 写道:

sunway

未读,
2007年5月24日 08:35:082007/5/24
收件人 高性能网络编程邮件列表
1。3000个连接下的select模式也需要接近50个线程,50个线程+监听线程,线程切换带来的开销超过iocp,而且编码非常麻烦,需要自己来
分配用户倒合适的线程。IOCP把这些都做了。
2。正常情况下在并发10000连接请求是在热点时间,比如晚上7点等,过了这个时间段人数就会少很多,10000个并发连接,并不是每秒都有
10000个连接请求,如果服务器做了最大并发连接限制的话,10000个连接请求在每秒3000处理能力的情况下4秒能处理完,login用户多等个
几秒也没有关系,如果是select模式剩下的7000连接用户需要重新连接了,付出的开销更大。

On 5月24日, 下午8时13分, qiaojie <qiao...@gmail.com> wrote:
> 并发连接数意义不大,主要看你的每秒最大能处理的登陆请求数,如果你的后端最大每秒只能处理3000个请求,而你接受10000多个连接在用户层就没什么意义, 还不如缓冲在网络层,网络层缓冲满了系统就开始拒绝连接,这可以防止风暴连接的时候把服务器压垮。
> 至于登陆服务器用select毫无问题,因为都是短时的连接,一般你select的时候大多数情况数据已经可读,不存在大量idle
> connection的情况,用iocp不会有什么性能上的优势。
>

> 在07-5-24,sunway <sunhui...@gmail.com> 写道:


>
>
>
>
>
> > 个人感觉登陆服务器有必要用完成端口或者EPOLL,
> > 1.因为登陆服务器是并发连接多.
> > 2.单连接通讯数据量小。
> > 3.用户不介意等个几秒。
> > 我做过的loginserver并发连接都比较高,经常5k并发连接以上。
> > 我一般的做法是前面2*CPU个数的iocp线程,后面8~12个db线程。基本上够用了。
>
> > On May 24, 4:37 pm, qiaojie <qiao...@gmail.com> wrote:
>
> > 这种应用没必要用什么IOCP,徒增编程复杂度。你的问题是没有做拥塞控制,接受连接的吞吐量超过了后端数据库IO的吞吐量,导致一段时间以后累积了很多后端来
> > 不及处理的连接,你又不控制拥塞导致内存耗尽。其实用非阻塞的select轮询就足够了,网络层自动的帮你做了拥塞控制从而简化了编程。
>
> > > 在07-5-24,关中刀客 <guanzhongda...@gmail.com> 写道:
>
> > > > 大家好:
> > > > 最近在设计这个"登陆服务器"。设计了几个方案都感觉缺陷很大。这个"登陆服务器"主要的职责是接受客户端的登陆请教(帐号+密码)。然后发
>
> > 给"数据库服务器"验证,如果数据库里面有的话,"数据库服务器"发包(包括这个用户的具体信息)给"登陆服务器",然后"登陆服务器"把这个信息发给
> > > > 一个"大厅服务器",然后把这个"大厅服务器"的port 和IP发回给客户端,客户端在区连接"大厅服务器".............
>
> > > > 为了同时可容纳很多的人"登陆",我在"登陆服务器"中使用IOCP连接和接受客户端请求,单独开一个线程接受"数据库服务器"的数据,同
> > > > 时又有几个socket连接着"大厅服务器"。
> > > > 现在的问题就是:在这个"完成端口"的线程池处理函数中,只需要recv一次客户端的信息。而我每次有客户端连接的时候。都要new全局的"句
>
> > 柄结构"和"数据结构体",把它和IOCP连接起来。等受到了消息后,就通过和"数据库服务器连接的socket"法给"服务器服务器"。这样子,我感
> > > > 觉没有合理的运用iocp,并贴会new很多的"结构体",然后只能在返回给客户端消息后delete
> > .这样子程序很快就没空间可分配了,尽管我只用
> > > > 了"对象池"
> > > > 请大家根据自己的经验指点一下,谢谢.- Hide quoted text -
>

qiaojie

未读,
2007年5月24日 09:07:122007/5/24
收件人 dev4s...@googlegroups.com
开那么多线程干吗?我从来都是单线程non-blocking select,轮询一遍5000个socket是用不了多少时间的(大约几个ms),,登陆没必要提供很快的响应时间,你可以间隔上百ms才轮询一次,在收到一组用户数据后再批量传送给数据库验证,这里可以用线程池来提高IO使用效率。
至于连接则由网络层负责缓冲,你可以把缓冲区设置的大一些改善连接吞吐量,比方说我每隔50ms查询一遍侦听端口,连接缓冲设置为100,这样理论上说我每秒最多可以接受2000个新连接,缓冲区满了网络层就不再响应TCP握手消息了,这样最多让用户收到个连接超时的错误,对服务器来说不会造成很大的开销,反之你不加控制一股脑全连接进来又来不及处理,时间一长应用层累积了大量未处理连接可能导致资源耗尽,如果遇到DDOS攻击那么情况就更严重了。

 
在07-5-24,sunway <sunh...@gmail.com> 写道:

sunway

未读,
2007年5月24日 09:19:202007/5/24
收件人 高性能网络编程邮件列表
1,对连接数当然有限制。
2,ddos攻击应用软件来抵御根本就没有可能。
3,你也承认loginserver的用户对于实时性没有需求,那么他们任一个用户
都是idle的, 只要服务器能在1~5内给回应就OK了。按你的说法应该更适合
用iocp/epoll。
4,你的处理逻辑里面做了大量的轮询遍历操作,比较费CPU。

On 5月24日, 下午9时07分, qiaojie <qiao...@gmail.com> wrote:
> 开那么多线程干吗?我从来都是单线程non-blocking

> select,轮询一遍5000个socket是用不了多少时间的(大约几个ms),,登陆没必要提供很快的响应时间,你可以间隔上百ms才轮询一次,在收到一 组用户数据后再批量传送给数据库验证,这里可以用线程池来提高IO使用效率。


> 至于连接则由网络层负责缓冲,你可以把缓冲区设置的大一些改善连接吞吐量,比方说我每隔50ms查询一遍侦听端口,连接缓冲设置为100,这样理论上说我每秒最 多可以接受2000个新连接,缓冲区满了网络层就不再响应TCP握手消息了,这样最多让用户收到个连接超时的错误,对服务器来说不会造成很大的开销,反之你不加 控制一股脑全连接进来又来不及处理,时间一长应用层累积了大量未处理连接可能导致资源耗尽,如果遇到DDOS攻击那么情况就更严重了。
>

> 在07-5-24,sunway <sunhui...@gmail.com> 写道:

> > > - 显示引用的文字 -- 隐藏被引用文字 -
>
> - 显示引用的文字 -

qiaojie

未读,
2007年5月24日 09:29:022007/5/24
收件人 dev4s...@googlegroups.com
傻,一旦接收到用户登陆数据就不再需要读取了,当然没必要再select了,一般来说连接建立到select会有一定的间隔时间,这点时间足够用户把登陆数据传过来了,因此第一次select的时候大部分情况有数据可读。对于长时间没有数据可读的连接做超时处理就可以了。至于DDOS么,最低要求是在被攻击的时候不应该把服务器压的资源耗尽而宕机,至于是否还能够正常服务,那另当别论。


 
在07-5-24,sunway <sunh...@gmail.com> 写道:

关中刀客

未读,
2007年5月24日 09:44:082007/5/24
收件人 高性能网络编程邮件列表
我想到一个思路:
采用IOCP,然后设置一个IOCPDispatchThread, 每次客户连接的句柄结构和发送的overlapped数据结构都存放到一
个map表里面,主键用这个这个连接socket,然后把它的包结尾加上这个socket传递给"数据库服务器",数据库反正完后返回信息(当然结尾有
这个socket),然后"登陆服务器"根据这个socket从map表里面找到这个"句柄结构体和overlapped数据结构体",投递
WSASend给客户端信息。然后在iocp的线程里面受到send OK 消息时回收这个"句柄结构体和overlapped数据结构体"

大家感觉怎么样?

liam

未读,
2007年5月24日 10:02:242007/5/24
收件人 高性能网络编程邮件列表
接受连接单独一个线程还是有必要的.数据包过来后我们是否应该产生一个session代表此次会话.同时这个session会发往数据库并处理后返回,
因为可能数据库返回包中的socket已经不代表原来的客户端了?不知道前辈们怎么看的.

关中刀客

未读,
2007年5月24日 10:18:062007/5/24
收件人 高性能网络编程邮件列表
"数据库服务器端返回的socket是刚开始给他发的时候故意加进去的"怎么会不一样呢?
这个socket在没有等到"数据库服务器段返回+返回给客户端"这两件事完成是不会关闭的
关键的问题就是:
怕一个很多连接和登陆,那么前面的分配的全局"句柄结构体"和"overlapped数据结构体"还没回收完,就有很多的连接登陆,这样子
我怕再跟他们分配这些结构体会失败

Ghost Cheng

未读,
2007年5月24日 10:23:172007/5/24
收件人 dev4s...@googlegroups.com
"这个socket在没有等到"数据库服务器段返回+返回给客户端"这两件事完成是不会关闭的"

如果是客户端主动关闭呢?考虑过没有?
当客户端主动断开了连接后,这个socket值,也许会在accept时分配给另一个客户端。


--

Sincerely,
Ghost Cheng
Email : ghost...@gmail.com
Web : http://www.GhostSoft.net

关中刀客

未读,
2007年5月24日 10:50:072007/5/24
收件人 高性能网络编程邮件列表
高,这个问题确实挺严重阿,一般是"登陆服务器"返回"大厅服务器"的port和ip
,客户端受到后就断开连接,然后去连接"大厅服务器"。但是如果在这个中间客户端断开了连接就.......,因为在iocp的线程里面得到登陆信息后
就没有再recv了,客户端断开了也就没办法通知了,好像.........


On 5月24日, 下午10时23分, "Ghost Cheng" <ghost.ch...@gmail.com> wrote:
> "这个socket在没有等到"数据库服务器段返回+返回给客户端"这两件事完成是不会关闭的"
>
> 如果是客户端主动关闭呢?考虑过没有?
> 当客户端主动断开了连接后,这个socket值,也许会在accept时分配给另一个客户端。
>

> Email : ghost.ch...@gmail.com
> Web :http://www.GhostSoft.net- 隐藏被引用文字 -
>
> - 显示引用的文字 -

Ghost Cheng

未读,
2007年5月24日 10:55:422007/5/24
收件人 dev4s...@googlegroups.com
所以,服务器之间的数据交互,必须都带上给每个客户端分配的唯一标志,当收到另一个服务器传来的针对某一个客户端的数据时,第一件要做的事情,就是查询这个客户端是否还在线。
通常我会将所有在线的用户,按ID、名字、或者临时ID,存进一个hashmap中,下线后就删掉,收到其他服务器传来的消息是,先找在这个map中查询一下,user是否在线,再做处理。

On 5/24/07, 关中刀客 <guanzho...@gmail.com> wrote:


--

Sincerely,
Ghost Cheng
Email : ghost...@gmail.com
Web : http://www.GhostSoft.net

Ghost Cheng

未读,
2007年5月24日 09:27:442007/5/24
收件人 dev4s...@googlegroups.com
象LoginServer这样的需要处理大量并发连接,并且每个连接之间没有需要交互的逻辑关系,这种情况显然最适合使用IOCP或EPOLL。

IOCP/EPOLL,可以最大程度的的处理大量并发连接,这些连接分配到不同的线程里去处理,没有任何需要线程间同步的地方,这种情况下,多线程+IOCP/EPOLL
显然比 单线程non-blocking 更加符合应用需求,以及能够更加发挥系统的最佳性能。

单线程只该应用在复杂逻辑的服务器应用上,比如游戏的场景服务器,那种情况下,每个客户端连接之间,都存在很多需要共享的数据,多线程处理的话,需要大量的线程同步操作。

关中刀客

未读,
2007年5月24日 11:27:272007/5/24
收件人 高性能网络编程邮件列表

ghost 真高手,对于你说的那个,我认为主要应用在"已经正常的登陆,连接大厅服务器,并且进入了一个"战区了",这个时候我们在内存中会村一部分
的用户资料,用什么内存影射==都可以,然后用心条包来判断用户是否还"活"着。

但是在"登陆服务器的时候",在IOCP的处理线程中,我们接受到了客户端的数据后,虽然客户端只会发送一次信息,但是我们在recv消息受到登陆信息
后在此投递WSARecv,用于监听客户端是否断开,然后用全局的一系列bool值来判断每次socket是否已经改变

当然这个也是ghost的思想,我只是在重复了一下,呵呵,详细的细节我要做好了才能在说了
谢谢大家阿,3KS

On 5月24日, 下午10时55分, "Ghost Cheng" <ghost.ch...@gmail.com> wrote:
> 所以,服务器之间的数据交互,必须都带上给每个客户端分配的唯一标志,当收到另一个服务器传来的针对某一个客户端的数据时,第一件要做的事情,就是查询这个客户 端是否还在线。
> 通常我会将所有在线的用户,按ID、名字、或者临时ID,存进一个hashmap中,下线后就删掉,收到其他服务器传来的消息是,先找在这个map中查询一下, user是否在线,再做处理。
>

> > > Web :http://www.GhostSoft.net-隐藏被引用文字 -

Yun Fan

未读,
2007年5月24日 22:14:042007/5/24
收件人 dev4s...@googlegroups.com
是否可以把用户的帐号和密码都cache 起来认证呢? 避免数据库压力?

关中刀客

未读,
2007年5月24日 22:48:022007/5/24
收件人 高性能网络编程邮件列表
这样子就太大了吧
注册和登陆不是一个服务器,在"数据库服务器"那边因该把"合适"的信息先放到
内存中,然后固定的时间把这些写入数据库,这样子可以实现缓冲的功能

On 5月25日, 上午10时14分, "Yun Fan" <fanyun2...@gmail.com> wrote:
> 是否可以把用户的帐号和密码都cache 起来认证呢? 避免数据库压力?

qiaojie

未读,
2007年5月25日 03:23:032007/5/25
收件人 dev4s...@googlegroups.com
用select只是为了简化编程,不是出于性能考虑。
至于在性能方面,iocp/epoll不会有很大的优势,用iocp/epoll的前提是:1、连接数大,2、有大量idle connection。而LoginServer虽然连接数大,但是几乎没有idle connection,所以难以发挥他们的性能优势。特别是epoll因为要频繁的注册事件删除事件,反而抵消了带来的好处。当然,这只是基于我个人的理论分析,谁有兴趣的话不妨来做个性能基准测试。


 
在07-5-24,Ghost Cheng <ghost...@gmail.com> 写道:

Ghost Cheng

未读,
2007年5月25日 03:35:492007/5/25
收件人 dev4s...@googlegroups.com
第一,不赞成这句话:"而LoginServer虽然连接数大,但是几乎没有idle connection"。

LoginServer,通常是直接连接到数据库上操作,对数据库访问时,可以肯定,有大量的idle connection 在等待数据库的返回结果。

第二,更不赞成这句话:"至于在性能方面,iocp/epoll不会有很大的优势,


用iocp/epoll的前提是:1、连接数大,2、有大量idle connection。"

如果你这么认为,那我真的不知道该说什么了。。。。
在网络游戏的服务器设计上,可以肯定的说IOCP/EPOLL的性能,绝对不是select模型可比的。游戏的实时性要求不高么?游戏中的玩家连接,是不可能存在大量的idle
connection 的。那么按照你的想法,使用select模型的服务器,能带的了多少玩家同时在线?这个问题似乎已经有N多的实例数据了。

DEMON

未读,
2007年5月25日 05:06:362007/5/25
收件人 dev4s...@googlegroups.com
 
曾经做过测试,在某些情况下,EPOLL未必比SELECT更具有优势。
EPOLL的是在大连接数,但是大量连接是空闲连接的情况下,表现比select优异。
象这种loginserver,个人感觉,应该是短连接吧,
用哪个个模型应该区别不是太大,如果并发真的太大的话,估计主要问题就是数据库的问题。
 
至于select,我觉得也不用怀疑它的效率,用ACE的select_reactor做过测试,
设计的时候是单线程I/O,收到信息就put进队列,由后台线程处理。
测试程序用900的长连接,无间断的发包,整个程序运行的时候
CPU占用仅15%左右。反而是数据库先顶不住,CPU一直狂涨。
虽然连接数没有IOCP/EPOLL那么多,但是如果做loginserver,应该也足够了。

DEMON
2007-05-25

发件人: Ghost Cheng
发送时间: 2007-05-25 16:12:18
抄送:
主题: Re: 关于"登陆服务器"的架构设计

qiaojie

未读,
2007年5月25日 09:21:002007/5/25
收件人 dev4s...@googlegroups.com
我的论述基于对select//iocp/epoll实现机制的理论分析,我没有做过实际的测试,可能不一定正确。不过我前段时间做的社区游戏服务器,因为用的.net不支持IOCP,所以就用了select,做了点简单的压力测试:1000个测试客户端不断发送移动消息,上行带宽300K,下行4M,CPU占用率30%,客户只要求最大1000并发数,但是实际运行我想跑2000个以上的客户端都都不会有什么问题。在做之前我对select做过一些性能测试,对2000个连接进行一次select轮询大约耗时6~10ms,我设定每隔100ms进行一次轮询,这样最多只需要浪费10%的CPU时间就可换取更简单的代码和更快的交付,这个买卖值得。这是我近期做的一个比较得意的项目,很好的秉承了我的实用主义原则,以后若有机会我把这个项目重写一遍传上来给大家玩玩。
 
 

 
在07-5-25,Ghost Cheng <ghost...@gmail.com> 写道:

Ghost Cheng

未读,
2007年5月25日 09:37:152007/5/25
收件人 dev4s...@googlegroups.com
"对2000个连接进行一次select轮询大约耗时6~10ms,我设定每隔100ms进行一次轮询"

你所说的轮询耗时6~10MS,加上了recv数据,memcpy,压入数据队列的时间么?

"每隔100ms进行一次轮询" 对于实时性要求比较高的MMO来说,这是不可忍受的。你每轮询10次,就给服务器和用户之间的通讯浪费了1秒钟的时间。

另外你测试用的1000个客户端,使用了几台物理客户端机器?如果数量不多的话,那么根本就没有正真模拟出1000个客户端的并发连接。那些机器根本不可能模拟出几百个连接同时发送数据。几乎可以肯定,你的这1000个连接发送到服务器的数据,大多是排着队进来的。

Ghost Cheng

未读,
2007年5月25日 09:47:532007/5/25
收件人 dev4s...@googlegroups.com
另外,根据业务需求的不同,实际应用中的数据交换量远远大于我们测试中的数据。
拿征途来说,单个客户端每秒中的数据下载量超过20K。
30%的CPU负载,只处理了1000个想像中的"并发"客户端的移动消息。
如果再加上其他,场景数据,攻击数据,角色数据等等,并且还有N多的数据,需要从服务器上发送到各个客户端。你觉得呢?

qiaojie

未读,
2007年5月25日 10:39:042007/5/25
收件人 dev4s...@googlegroups.com
这6~10ms是纯select消耗的时间,至于recv,memcpy,不管你用什么IO模型都是要做的,这部分开销是一样的。每隔100ms进行轮询的话一个请求来回的最大延迟是0.2秒,这个参数是基于我的Server每秒跟新频率10Hz来设定的。一般来说普通人的反应速度是150ms,RTS游戏在100ms延迟的情况下就可以流畅的玩,FPS的话50ms,100ms对于一般的mmo来说是足够的。
至于单个客户端每秒中的数据下载量超过20K,对这个数据偶表示非常的怀疑,这样3000个连接需要60MByte带宽,一般连到交换机上的网卡也就100Mbit带宽,难道你是通过千兆网卡连接IDC的?按征途几十万在线人数算,你们公司租用的带宽可真不小哦。

Yun Fan

未读,
2007年5月25日 10:39:142007/5/25
收件人 dev4s...@googlegroups.com
正好借这个帖子问一个我一直很困惑的问题。 如何才能模仿真正的1000 甚至10000 个用户并发上来的情况呢? 谁都不可能有这么多机器的。 



--
Regards

FanYun

qiaojie

未读,
2007年5月25日 10:43:032007/5/25
收件人 dev4s...@googlegroups.com
你在公司里面就不愁没有机器了


 
在07-5-25,Yun Fan <fanyu...@gmail.com> 写道:

Yun Fan

未读,
2007年5月25日 10:47:162007/5/25
收件人 dev4s...@googlegroups.com
不解。 一般要多少物理机器才能够模仿10000个并发用户呢?
--
Regards

FanYun

qiaojie

未读,
2007年5月25日 11:00:052007/5/25
收件人 dev4s...@googlegroups.com
那要看你测试客户端怎么实现的,我用的是最简单的一个客户端一个线程,一台机器跑200多个线程是没有问题的,1w个么只需要动用50台机器。当然机器不够你可以优化一下,既然服务器能够处理1000个客户端,那么你测试程序模拟1000个客户端也不存在任何问题,何况测试程序只是发送消息不需要做逻辑处理,应该比服务器模拟的更多才对。

Ghost Cheng

未读,
2007年5月25日 10:44:272007/5/25
收件人 dev4s...@googlegroups.com
100ms对于一般的mmo来说是足够的,对于单个客户端来说,当然是够的,
但是对于超过1000,2000,甚至更多的客户端来说呢?

另外,征途的流量确实比其他的游戏要大一些。

qiaojie

未读,
2007年5月25日 12:22:442007/5/25
收件人 dev4s...@googlegroups.com
1000个客户端也是延迟100ms,这个跟客户端数量没有关系的。

Ghost Cheng

未读,
2007年5月25日 12:45:252007/5/25
收件人 dev4s...@googlegroups.com
我是说,你等了100MS之后再处理1个客户端的数据,和等了100MS后,再处理1000个客户端的数据是不一样的。
服务器上每1MS都是很重要的,不应该把时间浪费在这里。

lijie

未读,
2007年5月25日 13:26:462007/5/25
收件人 dev4s...@googlegroups.com
在07-5-26,Ghost Cheng <ghost...@gmail.com> 写道:
我是说,你等了100MS之后再处理1个客户端的数据,和等了100MS后,再处理1000个客户端的数据是不一样的。
服务器上每1MS都是很重要的,不应该把时间浪费在这里。

Ghost Cheng

未读,
2007年5月25日 13:01:472007/5/25
收件人 dev4s...@googlegroups.com
总之,在针对大量并发连接的时候,IOCP/EPOLL模型的效率,根本不是select能够比拟的。IOCP/EPOLL,正是为了解决select各项缺点,才被发明出来的。
select这种模型,在处理成千上万的并发连接时,不能做到最快速的响应。
就算你1000个客户端轮询一遍只需要6~10MS,但是IOCP/EPOLL,对于客户端响应是即时的,我们不需要刻意去做什么100MS的等待,不需要把CPU时间花在毫无意义的轮询上,当有数据处理时,就处理,当没有数据处理时,线程就可以idle。
你在处理1000个连接的时候,也许你觉得select可以满足你的要求,但是当你的业务逻辑开始增长,并发连接数开始增加的时候,负载也会成几何级的增长。那你的用户数量更多的时候,你会发现select是多么让人郁闷的模型。几十年前的技术是用来满足当时的情况的,现在时代变了,需求也变了。

PS:况且,你的测试的环境,并不是真正的1000个并发连接,每台机器200个线程发送数据,已经让第一个线程和最后一个线程工作的时间间隔很大了。个人认为你去做那100MS的等待,无非就是将这100MS内收到的数据集中到一批处理罢了。

qiaojie

未读,
2007年5月25日 23:04:362007/5/25
收件人 dev4s...@googlegroups.com
不是在select上等待时间的,主循环是这样的:
select连接状态
接收并处理用户消息
刷新游戏状态
将发送缓冲内的数据发送给客户端
如果还有空闲时间则sleep

 
在07-5-26,Ghost Cheng <ghost...@gmail.com > 写道:
我是说,你等了100MS之后再处理1个客户端的数据,和等了100MS后,再处理1000个客户端的数据是不一样的。

qiaojie

未读,
2007年5月25日 23:53:442007/5/25
收件人 dev4s...@googlegroups.com
嘿嘿,有数据就处理这种模式恰恰就是低效的根源,要提高效率就应该batch处理。响应时间跟性能是矛盾的,举个例子吧,假设用户平均每秒钟发送20个请求,如果你及时响应的话则需要20次recv调用,而如果服务器以10Hz的频率轮询,那么实际上服务器每秒不到10次recv调用,节省了一半的recv开销。另外你要及时响应就要使用多线程,这增加了很多线程切换开销。所以这个例子里轮询的IO性能比及时响应至少提高一倍。
当然了,我也承认select是存在着局限性,在上例中我也确实可以用epoll优化掉select轮询的开销,但是只能提高不到10%的整体性能,意义并不大。用什么方案还是要根据具体的应用来分析,但是把iocp/epoll当成是万能药,把这做为提高性能的唯一方法,而不去分析具体应用的特性不去合理的分配系统资源,这样做出来的系统反而更低效。把采用什么IO模式当成判断系统性能的标准,这种判断幼稚了点。


 
在07-5-26,Ghost Cheng <ghost...@gmail.com> 写道:
总之,在针对大量并发连接的时候,IOCP/EPOLL模型的效率,根本不是select能够比拟的。IOCP/EPOLL,正是为了解决select各项缺点,才被发明出来的。

Ghost Cheng

未读,
2007年5月26日 00:19:262007/5/26
收件人 dev4s...@googlegroups.com
hoho~~看来微软和开源社区的一帮白痴,花了那么多精力开发出了两个更加低效的IO模型。。。嗯,佩服。

"有数据就处理这种模式恰恰就是低效的根源,要提高效率就应该batch处理"
个人观点,你这是图形渲染的方面搞的太多,将显卡和网络联想到一起了,网络编程和对显卡的渲染管线编程并不一样。socket编程,你必须考虑很多的非人为的,不可控的突发事件。batch处理recv数据,想法也许是好的,但是如果当你的主循环idle时,socket的buffer满了怎么办?
(PS:不要认为我只是个写写服务器代码的家伙,对3D方面一无所知,在这里大放厥词,事实上我写过不止一个图形渲染引擎。)

"另外你要及时响应就要使用多线程,这增加了很多线程切换开销"
难道你看到的使用IOCP/EPOLL的代码,都是开了几十上百个GET线程?通常我们使用IOCP/EPOLL时,所开的线程数量都是根据CPU数量做了优化,得到的结果。可以保证最大程度的合理利用CPU资源。而在这里使用单线程,恰恰浪费了很多CPU周期,这也是多线程处理的概念被发明的原因。


"用什么方案还是要根据具体的应用来分析"
这句话我倒是赞同的,依据以往的经验和案例,并发连接数大于1000的就已经不太适合select模型了。当然,也许你的项目,通讯量并不大,致使你的测试结果,看起来能够让你接受。

"把采用什么IO模式当成判断系统性能的标准", 貌似这种对我的回帖断章取义的做法更加的幼稚。

qiaojie

未读,
2007年5月26日 00:58:122007/5/26
收件人 dev4s...@googlegroups.com
hoho,看来你也是把我的话断章取义来理解,这样下去恐怕是要发展成意识形态之争了,好吧,我先收回我最后说的那句话。你也先不要那么激动,大家摆事实讲道理。
 
>个人观点,你这是图形渲染的方面搞的太多,将显卡和网络联想到一起了,网络编程和对显卡的渲染管线编程并不一样。socket编程,你必须考虑很多的非人为的,不可控的突发事件。batch处理recv数据,想法也许是好的,但是如果当你的主循环idle时,socket的buffer满了怎么办?
 
首先正常情况下recv buffer不可能满,就算用户故意发送巨量请求或者因为网络阻塞把recv buffer撑满了,那也只是在客户端的send buffer里缓存,如果send buffer也满了则客户端阻塞,你觉得这有什么问题?反倒是很好的帮你做了拥塞控制,同时也可以防止黑客攻击把服务器压垮了。事实上我通常会刻意把recv buffer设置的小一些。
 
 
>难道你看到的使用IOCP/EPOLL的代码,都是开了几十上百个GET线程?通常我们使用IOCP/EPOLL时,所开的线程数量都是根据CPU数量做了优化,得到的结果。可以保证最大程度的合理利用CPU资源。而在这里使用单线程,恰恰浪费了很多CPU周期,这也是多线程处理的概念被发明的原因。
 
你在线程等待事件->处理->再等待,这个从等待到唤醒的过程难道没有系统开销吗?另外你也不可能多线程处理游戏逻辑吧?还得另外用一个队列来排队用户请求,这不是开销吗?至于单线程恰恰浪费了很多CPU周期,我想听听你理由。
 
 
>这句话我倒是赞同的,依据以往的经验和案例,并发连接数大于1000的就已经不太适合select模型了。当然,也许你的项目,通讯量并不大,致使你的测试结果,看起来能够让你接受。
在你的论述中,我看到的更多的是你根据经验的判断,如果你能拿出更多的分析和量化数据的话我想会更有说服力。

Ghost Cheng

未读,
2007年5月26日 01:15:192007/5/26
收件人 dev4s...@googlegroups.com
多线程处理游戏逻辑当然是不可能的。不过最普遍的做法是,游戏逻辑由单独的服务器来完成,并不需要处理成千上万的socket连接,而真正与用户进行网络数据交换的网关服务器,并不需要处理游戏逻辑。N个GET线程的recv完了之后,并不一定需要将数据压到一个队列中,可以直接send到逻辑服务器。

"你在线程等待事件->处理->再等待,这个从等待到唤醒的过程难道没有系统开销吗"
如果你认为这个是在浪费CPU资源,那么多线程这个概念,不要也罢。单线程"足以高效"的处理一切了。

"至于单线程恰恰浪费了很多CPU周期,我想听听你理由。"
最简单的例子:按你的说法,你的主循环轮询完了之后的,如果还不到100MS,那么就sleep。
那么这个时间就是被浪费的CPU周期。这时本可以利用CPU的空闲,做其他的操作,或将CPU交给另一个线程工作。
人们发明了多线程编程,就是为了更好的利用,单线程处理的时候CPU被闲置的情况。


好了,我认为这个问题继续争论下去,已经没什么意义了。注意我用的是"争论"而不是"讨论",这已经不是讨论了,而是毫无意义的争论。
既然你这么坚持的认为select比IOCP/EPOLL更高效,看起来,我除了表示一些反对意见以外,已经没有必要再争论什么了。各自按各自的想法去做吧。

qiaojie

未读,
2007年5月26日 01:50:582007/5/26
收件人 dev4s...@googlegroups.com
呵呵,看来你是完全听不进我的观点了,不过我到是建议你修改一下你那个征途的网关服务器,不立刻发送消息到后端,先缓存一段时间再一起发送,同时向用户发送消息时也不要马上发送,先缓存在自己的buffer里,一段时间后再一起发送,看看这样有没有性能上的提升。

Ghost Cheng

未读,
2007年5月26日 04:08:122007/5/26
收件人 dev4s...@googlegroups.com
"不立刻发送消息到后端,先缓存一段时间再一起发送,同时向用户发送消息时也不要马上发送,先缓存在自己的buffer里,一段时间后再一起发送"

这个我赞同,现在也确实是这么做的,我会将消息缓存一下,满了64K才发送,当然有时间限制,超时后,直接发送。

但是在响应socket的数据时,仍然是即时响应。

Yun Fan

未读,
2007年5月26日 05:28:062007/5/26
收件人 dev4s...@googlegroups.com
这里有征途的主力开发人员啊? 敬佩敬佩,百万人在线啊。 这么短时间就达到这个规模真是不简单。

sunway

未读,
2007年5月26日 06:54:012007/5/26
收件人 高性能网络编程邮件列表
看来qiaojie没有深入了解过TCP协议.
1,TCP有滑动窗口,接受方的BUFFER满了会通知发送方.
1,TCP协议内部已经缓冲算法,对于小包会缓冲一段时间再发送,所以很多实时性高的应用会用UDP或者关掉TCP的缓冲算法,因此程序根本不用做这样
的优化.相反,很多游戏服务器关掉缓冲算法的来提高实时性,对于游戏网关这样程序不用延迟发送,有数据直接发就OK了

On 5月26日, 下午1时50分, qiaojie <qiao...@gmail.com> wrote:
> 呵呵,看来你是完全听不进我的观点了,不过我到是建议你修改一下你那个征途的网关服务器,不立刻发送消息到后端,先缓存一段时间再一起发送,同时向用户发送消息 时也不要马上发送,先缓存在自己的buffer里,一段时间后再一起发送,看看这样有没有性能上的提升。...
>
> 阅读更多
>
> 在07-5-26,Ghost Cheng <ghost.ch...@gmail.com> 写道:
>
>
>
>
>
> > 多线程处理游戏逻辑当然是不可能的。不过最普遍的做法是,游戏逻辑由单独的服务器来完成,并不需要处理成千上万的socket连接,而真正与用户进行网络数据交 换的网关服务器,并不需要处理游戏逻辑。N个GET线程的recv完了之后,并不一定需要将数据压到一个队列中,可以直接send到逻辑服务器。


>
> > "你在线程等待事件->处理->再等待,这个从等待到唤醒的过程难道没有系统开销吗"
> > 如果你认为这个是在浪费CPU资源,那么多线程这个概念,不要也罢。单线程"足以高效"的处理一切了。
>
> > "至于单线程恰恰浪费了很多CPU周期,我想听听你理由。"
> > 最简单的例子:按你的说法,你的主循环轮询完了之后的,如果还不到100MS,那么就sleep。
> > 那么这个时间就是被浪费的CPU周期。这时本可以利用CPU的空闲,做其他的操作,或将CPU交给另一个线程工作。
> > 人们发明了多线程编程,就是为了更好的利用,单线程处理的时候CPU被闲置的情况。
>
> > 好了,我认为这个问题继续争论下去,已经没什么意义了。注意我用的是"争论"而不是"讨论",这已经不是讨论了,而是毫无意义的争论。
> > 既然你这么坚持的认为select比IOCP/EPOLL更高效,看起来,我除了表示一些反对意见以外,已经没有必要再争论什么了。各自按各自的想法去做吧。
>

> > On 5/26/07, qiaojie <qiao...@gmail.com> wrote:
>
> > hoho,看来你也是把我的话断章取义来理解,这样下去恐怕是要发展成意识形态之争了,好吧,我先收回我最后说的那句话。你也先不要那么激动,大家摆事实讲道理 。
>
> > >个人观点,你这是图形渲染的方面搞的太多,将显卡和网络联想到一起了,网络编程和对显卡的渲染管线编程并不一样。socket编程,你必须考虑很多的非人为的 ,不可控的突发事件。batch处理recv数据,想法也许是好的,但是如果当你的主循环idle时,socket的buffer满了怎么办?
>
> > > 首先正常情况下recv buffer不可能满,就算用户故意发送巨量请求或者因为网络阻塞把recv
> > > buffer撑满了,那也只是在客户端的send buffer里缓存,如果send
>
> > buffer也满了则客户端阻塞,你觉得这有什么问题?反倒是很好的帮你做了拥塞控制,同时也可以防止黑客攻击把服务器压垮了。事实上我通常会刻意把recv
> > > buffer设置的小一些。
>

> > >难道你看到的使用IOCP/EPOLL的代码,都是开了几十上百个GET线程?通常我们使用IOCP/EPOLL时,所开的线程数量都是根据CPU数量做了优 化,得到的结果。可以保证最大程度的合理利用CPU资源。而在这里使用单线程,恰恰浪费了很多CPU周期,这也是多线程处理的概念被发明的原因。
>
> > 你在线程等待事件->处理->再等待,这个从等待到唤醒的过程难道没有系统开销吗?另外你也不可能多线程处理游戏逻辑吧?还得另外用一个队列来排队用户请求,这 不是开销吗?至于单线程恰恰浪费了很多CPU周期,我想听听你理由。
>
> > >这句话我倒是赞同的,依据以往的经验和案例,并发连接数大于1000的就已经不太适合select模型了。当然,也许你的项目,通讯量并不大,致使你的测试结 果,看起来能够让你接受。
>
> > > 在你的论述中,我看到的更多的是你根据经验的判断,如果你能拿出更多的分析和量化数据的话我想会更有说服力。
>
> > > 在07-5-26,Ghost Cheng <ghost.ch...@gmail.com> 写道:


> > > > hoho~~看来微软和开源社区的一帮白痴,花了那么多精力开发出了两个更加低效的IO模型。。。嗯,佩服。
>
> > > > "有数据就处理这种模式恰恰就是低效的根源,要提高效率就应该batch处理"
>
> > 个人观点,你这是图形渲染的方面搞的太多,将显卡和网络联想到一起了,网络编程和对显卡的渲染管线编程并不一样。socket编程,你必须考虑很多的非人为的, 不可控的突发事件。batch处理recv数据,想法也许是好的,但是如果当你的主循环idle时,socket的buffer满了怎么办?
>
> > > (PS:不要认为我只是个写写服务器代码的家伙,对3D方面一无所知,在这里大放厥词,事实上我写过不止一个图形渲染引擎。)
>
> > > > "另外你要及时响应就要使用多线程,这增加了很多线程切换开销"
>
> > 难道你看到的使用IOCP/EPOLL的代码,都是开了几十上百个GET线程?通常我们使用IOCP/EPOLL时,所开的线程数量都是根据CPU数量做了优化 ,得到的结果。可以保证最大程度的合理利用CPU资源。而在这里使用单线程,恰恰浪费了很多CPU周期,这也是多线程处理的概念被发明的原因。
>
> > > > "用什么方案还是要根据具体的应用来分析"
>
> > 这句话我倒是赞同的,依据以往的经验和案例,并发连接数大于1000的就已经不太适合select模型了。当然,也许你的项目,通讯量并不大,致使你的测试结果 ,看起来能够让你接受。
>
> > > > "把采用什么IO模式当成判断系统性能的标准", 貌似这种对我的回帖断章取义的做法更加的幼稚。
>

> > > > On 5/26/07, qiaojie <qiao...@gmail.com> wrote:
>
> > 嘿嘿,有数据就处理这种模式恰恰就是低效的根源,要提高效率就应该batch处理。响应时间跟性能是矛盾的,举个例子吧,假设用户平均每秒钟发送20个请求,如 果你及时响应的话则需要20次recv调用,而如果服务器以10Hz的频率轮询,那么实际上服务器每秒不到10次recv调用,节省了一半的recv开销。另外 你要及时响应就要使用多线程,这增加了很多线程切换开销。所以这个例子里轮询的IO性能比及时响应至少提高一倍。
>
> > 当然了,我也承认select是存在着局限性,在上例中我也确实可以用epoll优化掉select轮询的开销,但是只能提高不到10%的整体性能,意义并不大 。用什么方案还是要根据具体的应用来分析,但是把iocp/epoll当成是万能药,把这做为提高性能的唯一方法,而不去分析具体应用的特性不去合理的分配系统 资源,这样做出来的系统反而更低效。把采用什么IO模式当成判断系统性能的标准,这种判断幼稚了点。
>
> > > > > 在07-5-26,Ghost Cheng <ghost.ch...@gmail