« 假期好读书 | 返回首页 | 数据服务器的设计 »

多进程的游戏服务器设计

目前,我们的游戏服务器组是按多进程的方式设计的。强调多进程,是想提另外一点,我们每个进程上是单线程的。所以,我们在设计中,系统的复杂点在于进程间如何交换数据;而不需要考虑线程间的数据锁问题。

如果肆意的做进程间通讯,在进程数量不断增加后,会使系统混乱不可控。经过分析后,我决定做如下的限制:

  1. 如果一个进程需要和多个服务器做双向通讯,那么这个进程不能处理复杂的逻辑,而只是过滤和转发数据用。即,这样的一个进程 S ,只会把进程 A 发过来的数据转发到 B ;或把进程 B 发过来的数据转发到 A 。或者从一端发过来的数据,经过简单的协议分析后,可以分发到不同的地方。例如,把客户端发过来的数据包中的聊天信息分离处理,交到聊天进程处理。

  2. 有逻辑处理的进程上的数据流一定是单向的,它可以从多个数据源读取数据,但是处理后一定反馈到另外的地方,而不需要和数据源做逻辑上的交互。

  3. 每个进程尽可能的保持单个输入点,或是单个输出点。

  4. 所有费时的操作均发到独立的进程,以队列方式处理。

  5. 按功能和场景划分进程,单一服务和单一场景中不再分离出多个进程做负载均衡。

性能问题上,我是这样考虑的:

我们应该充分利用多核的优势,这会是日后的发展方向。让每个进程要么处理大流量小计算量的工作;要么处理小流量大计算量的工作。这样多个进程放在一台物理机器上可以更加充分的利用机器的资源。

单线程多进程的设计,个人认为更能发挥多核的优势。这是因为没有了锁,每个线程都可以以最大吞吐量工作。增加的负担只是进程间的数据复制,在网游这种复杂逻辑的系统中,一般不会比逻辑计算更早成为瓶颈。如果担心,单线程没有利用多核计算的优势,不妨考虑以下的例子:

计算 a/b+c/d+e/f ,如果我们在一个进程中开三条线程利用三个核同时计算 a/b c/d e/f 固然不错,但它增加了程序设计的复杂度。而换个思路,做成三个进程,第一个只算 a/b 把结果交给第二个进程去算 c/d 于之的和,再交个第三个进程算 e/f 。对于单次运算来算,虽然成本增加了。它需要做额外的进程间通讯复制中间结果。但,如果我们有大量连续的这样的计算要做,整体的吞吐量却增加了。因为在算某次的 a/b 的时候,前一次的 c/d 可能在另一个核中并行计算着。

具体的设计中,我们只需要把处理数据包的任务切细,适当增加处理流水线的长度,就可以提高整个系统的吞吐量了。由于逻辑操作是单线程的,所以另需要注意的一点是,所有费时的操作都应该转发到独立的进程中异步完成。比如下面会提到的数据存取服务。

对于具体的场景管理是这样做的:

玩家连接进来后,所有数据包会经过一个叫做位置服务的进程中。这个进程可以区分玩家所在的位置,然后把玩家数据分发到对应的场景服务进程中。这个位置服务同时还管理玩家间消息的广播。即,单个的场景(逻辑)服务并不关心每个数据包为哪几个玩家所见,而由这个服务将其复制分发。

当玩家切换场景,场景服务器将玩家的数据发送给数据服务,数据服务进程 cache 玩家数据,并将数据写入数据库。然后把玩家的新的场景编号发回位置服务进程,这样位置服务器可以将后续的玩家数据包正确的转发到新的场景服务进程中。

掉落物品和资源生产同样可以统一管理,所以的场景(逻辑)进程都将生产新物件的请求发给物品分配服务,由物品分配服务生产出新物件后通知位置服务器产生新物品。

这样一系列的做法,最终保证了,每个场景服务器都有一个唯一的数据源——位置服务进程。它跟持久化在数据库中的数据无关,跟时钟也无关。由此带来的调试便利是很显著的。

最近,面临诸多进程的设计时,最先面临的一个复杂点在于启动阶段。显然,每个进程都配有一套配置文件指出其它进程的地址并不是一个好主意。而为每个服务都分配一个子域名在开发期也不太合适。结果我们采取了一个简单的方案:单独开发了一个名字服务器。它的功能类似 DNS ,但是可以让每个进程自由的注册自己的位置,还可以定期汇报自己的当前状态。这样,我们可以方便的用程序查询到需要的服务。名字服务器的协议用的类似 POP3 的文本协议,这让我们可以人手工 telnet 上去查阅。我相信以后我们的维护人员会喜欢这样的设计的。:D

以上,国庆假期结束以来的工作。感谢项目组其他同事的辛勤编码。

Comments

对于游戏服务器这样的逻辑复杂的游戏服务器,对于数据的操作不可能全是单纯的增删改查,如果有一个操作分为多步,每一步都需要判断一些条件然后修改某个数据。像这样的操作因为多进程的原因只能是在一个服务器来做所有的的步骤才不会造成同步问题。又因为这样的数据操作还可能涉及的是多个玩家的数据,所以说这只能在专门管理数据的服务器上操作,但是这样子的话这个服务器就没有办法只提供简单的增删改查服务,而是在其同时做大量的游戏逻辑操作了。

我也在设计类似的游戏服务器,也属于多进程的,不过我做的非单线程,而是进程加多线程,只是数据流上怎么单向和双向上,还在考滤,数据回流怎如果设计较好

怎么可能不用多线程呢。。。。

异步IO,事件响应,逻辑处理
每个服务器上都有这个需求

我在win下正好凑巧实现了这样一个模型,是一个分布式的聊天室系统,专门提供给bbs和webbame做插件用。因为不同webgame可能存在特殊的逻辑分组,因此这个聊天系统不得不与webgame逻辑服务器进行交互以同步这些信息,此时我就采用了这样的结构。发现效果是非常好的。有一个最关键的宗旨恰巧和你一样:“让每个进程要么处理大流量小计算量的工作;要么处理小流量大计算量的工作。”,我觉得这个是核心,分线程或者进程其实都非常相似。我的程序中即分了进程也分了线程,分线程是为了异步队列。分进程是为了再满足版本快速更替更容易,因为一些边缘模块划分出去之后,往往可以在不修改主服务器的情况下,又其他人来编写,因为协议很集中,所以不需要别人来领悟主服务器的逻辑了。

需要多个模块输入时,可以把数据流汇总的位置做成独立的模块,专门负责把各个服务的输出信息做为输入收集在一起,并变成单一输出。

啊,图乱了,希望文字的意思说清楚了。

这个帖子我看过很久了,但是数据流的控制始终不能完全领会。

“每个进程尽可能的保持单个输入点,或是单个输出点”

如图

A----+
B----+----+ +E
C----+ D----+F
+G

D提供了一项服务,A,B,C三个不同的业务模块都会需要,但是D完全这项工作,需要协调E,F,G这另外三个服务器才能完成工作。

这样数据流好像就乱了,但是又没有特别好的解决方法。

请教:我们由于公司发展的需要,需要开发一个3层架构的系统,其中应用服务器的开发感觉比较棘手。应用服务器主要处理客户端的请求,做大量的计算,并且连接后台的数据库。在采用Socket Api开发,需要处理大量的问题,比如定义协议,处理客户连接,排队,等待。我们想采用一些比较新的技术,比如xml-rpc,soap之类,不知道有没有现有的服务器代码可以复用,或者这方面的书籍?

Almost forgot....Multi-process is good budget saver anyway, scalable, since you can move a process from one physical machine to another...but when it comes to syncronization...well a lot of replicated message to be syncronized, the more we divide MMOG computational resources into processes, the more repicational tasks to fill, and thus a lot of internal bandwidth and cpu overhead....

Hi Yun.
Haven't read it all, but multi-process is exactly what I'm implementing right now for the map servers, reason? Simple because multi-thread sucks, unreliable, unsafe, takes a bounch of phDs to make such a system, so multi-process might be a realistic choice. Multi-process-interchange shouldn't be a problem because Shared memory is the only right answer for high performance usage....

我什么都不懂,怎么办喔?

这样的思路似乎有点否定thread的感觉

thread提出有一部分原因就是来因为IPC效率低下,像这样使用多进程仅仅是把本来应该自己做的同步交给了OS去完成。而且最终数据要汇集到一个进程去最终完成,这样的话效率最终很可能就被这最后一个进程限制住,从而影响了整体的效率。

个人认为如果真的要用多进程,应当是用于提高并发程度,并利用进程对于数据的保护提高程序的健壮性。

没功力仔细看,不过我工作中管理SAP服务器,我天天看看它,认为它很先进,它就是多进程的.呵呵

怎么有点像MPI啊!
我觉得,这个东西理论上是可以的,但是实践起来怕不容易!另外究竟IPC效能是否高于nptl中的锁,还是个未知数。

云风是受了《Unix编程艺术》的影响吧,我也在看这本书,里面的一些思想确实值得借鉴

在未来的多核的时代,我更期待更多的诸如 Erlang 的东西出现和成熟。

进程管理上我们下了许多工夫来做,这是不能回避的。但是多个简短程序的版本维护,于我看来,比一个复杂程序的维护更简单一些。

1。既然云风可以做到进程间单输入点或者单输出点,那么也应该很容易做到线程间的单入点或单出点,况且线程间通讯的开销小于进程间通讯的开销。
2。多一个进程,管理和版本维护上也会带来不少麻烦,云风考虑过这些没?
3。我还是那句话,多线程是趋势,以后的UNIX/BSD编程是我们来写的,老的技术就让他们过去吧。

貌似大多数情况下数据处理本身的时间要比跨进程数据交换的时间短的多。这么做是不是得不偿失?

编程模型的转变是否意味着我们需要一门新语言呢。我想研究领域多年前就开始尝试了。

把 C 或者 C++ 扭曲到适应新的编程模型,个人认为是一个更不好的解决方案。

对于单纯使用长流水线的设计我是不看好的,这基本上属于分布式计算时代的思路,在多核时代多线程并发计算才是主流。Erlang已经展现了一部分面向未来的编程模型,不过我相信这个领域还远没有成熟。双核只是一个开端,未来可能就是百核甚至千核,编程模型的转变会变得越来越重要的。

前段时间不是讨论过用RPC实现C/S游戏框架的问题么,云风不用ICE的话,用什么来做RPC呢?

云风的BLOG内容丰富,很不错,以后要常来。关于语言方面,我觉得面向对象的语言可以更好的体现设计思想吧,在我看来,思想更重要一些。

关于ICE参与的游戏,听说是改为做游戏引擎了。

wish项目撤销的原因?是否和ice有关系?

我对 ICE 的了解仅仅来至于一些朋友的转述。其中一个朋友参与了叫 wish 的 MMO 项目。结果在 beta 测试的时候项目被撤掉了。当然这个项目是 ICE 小组亲自领导的 :)

ACE 经典的两卷本的书我仔细读过。

现在,我对 C++ 兴趣寥寥。

你知道ICE吗?全称是 Internet Communications Engine.如果你不了解的话,我建议你去看看。
www.zeroc.com

另外,有看过你讲 select,epoll,kqueue之类的麻烦处,另还有一种网络框架,ACE,可以解决以上问题,但就是过于复杂。

这样,如果服务器群集中有多个游戏逻辑服务器的话,各个服务器进程间的协作不是很麻烦. 一个core专门用来处理一件事,对于各个地图的区域也应该是单独用一个core来处理,那是否采用主/副逻辑服务器结构了?那主逻辑服务器也就主要做协调作用了. 学习中...

请教一下多线程处理和多进程处理?为何选择使用多进程?在多核的情况下,难道多个线程不能跑在不同的核上么?

考虑过erlang吗

我们现在用 freebsd

一个服务器上配置多少进程是配置问题,这个不太所谓的。

傻傻的问一下,如果正常的运作情况下,一个服务器上,一般平均会同时存在多少个进程在跑呢?

另:OS是WIN还是其他?

Post a comment

非这个主题相关的留言请到:留言本