logo资料库

百万用户级游戏服务器架构设计 .pdf

第1页 / 共24页
第2页 / 共24页
第3页 / 共24页
第4页 / 共24页
第5页 / 共24页
第6页 / 共24页
第7页 / 共24页
第8页 / 共24页
资料共24页,剩余部分请下载后查看
百万用户级游戏服务器架构设计 本文从最简单的游戏服务器架构开始讲起,结合主流的 WOW 等大型游戏服务器设计思 路和 mangos 的一些理念,一步一步揭开网络游戏服务器的架构设计方法,对初学者尤其有 帮助。0 D8 z+ [, w7 o9 _8 F0 i 本文不但针对大型网游的设计,对中小型以及休闲棋牌类游戏服务器的设计,也有很 大的启发作用。% Z# x+ 服务器结构探讨 -- 最简单的结构 所谓服务器结构,也就是如何将服务器各部分合理地安排,以实现最初的功能需求。所 以,结构本无所谓正确与错误;当然,优秀的结构更有助于系统的搭建,对系统的可扩展性 及可维护性也有更大的帮助。 好的结构不是一蹴而就的,而且每个设计者心中的那把尺都不相同,所以这个优秀结构 的定义也就没有定论。在这里,我们不打算对现有游戏结构做评价,而是试着从头开始搭建 一个我们需要的 MMOG 结构。 对于一个最简单的游戏服务器来说,它只需要能够接受来自客户端的连接请求,然后处 理客户端在游戏世界中的移动及交互,也即游戏逻辑处理即可。如果我们把这两项功能集成 到一个服务进程中,则最终的结构很简单: client ----- server 嗯,太简单了点,这样也敢叫服务器结构?好吧,现在我们来往里面稍稍加点东西,让 它看起来更像是服务器结构一些。 一般来说,我们在接入游戏服务器的时候都会要提供一个帐号和密码,验证通过后才能 进入。关于为什么要提供用户名和密码才能进入的问题我们这里不打算做过多讨论,云风曾 对此也提出过类似的疑问,并给出了只用一个标识串就能进入的设想,有兴趣的可以去看看 他们的讨论。但不管是采用何种方式进入,照目前看来我们的服务器起码得提供一个帐号验 证的功能。 我们把观察点先集中在一个大区内。在大多数情况下,一个大区内都会有多组游戏服, 也就是多个游戏世界可供选择。简单点来实现,我们完全可以抛弃这个大区的概念,认为一 个大区也就是放在同一个机房的多台服务器组,各服务器组间没有什么关系。这样,我们可 为每组服务器单独配备一台登录服。最后的结构图应该像这样:
loginServer gameServer | / | / client 该结构下的玩家操作流程为,先选择大区,再选择大区下的某台服务器,即某个游戏世 界,点击进入后开始帐号验证过程,验证成功则进入了该游戏世界。但是,如果玩家想要切 换游戏世界,他只能先退出当前游戏世界,然后进入新的游戏世界重新进行帐号验证。 早期的游戏大都采用的是这种结构,有些游戏在实现时采用了一些技术手段使得在切换 游戏服时不需要再次验证帐号,但整体结构还是未做改变。 该结构存在一个服务器资源配置的问题。因为登录服处理的逻辑相对来说比较简单,就 是将玩家提交的帐号和密码送到数据库进行验证,和生成会话密钥发送给游戏服和客户端, 操作完成后连接就会立即断开,而且玩家在以后的游戏过程中不会再与登录服打任何交道。 这样处理短连接的过程使得系统在大多数情况下都是比较空闲的,但是在某些时候,由于请 求比较密集,比如开新服的时候,登录服的负载又会比较大,甚至会处理不过来。 另外在实际的游戏运营中,有些游戏世界很火爆,而有些游戏世界却非常冷清,甚至没 有多少人玩的情况也是很常见的。所以,我们能否更合理地配置登录服资源,使得整个大区 内的登录服可以共享就成了下一步改进的目标。 服务器结构探讨 -- 登录服的负载均衡 回想一下我们在玩 wow 时的操作流程:运行 wow.exe 进入游戏后,首先就会要求我们输 入用户名和密码进行验证,验证成功后才会出来游戏世界列表,之后是排队进入游戏世界, 开始游戏... 可以看到跟前面的描述有个很明显的不同,那就是要先验证帐号再选择游戏世界。这种 结构也就使得登录服不是固定配备给个游戏世界,而是全区共有的。 我们可以试着从实际需求的角度来考虑一下这个问题。正如我们之前所描述过的那样, 登录服在大多数情况下都是比较空闲的,也许我们的一个拥有 20 个游戏世界的大区仅仅使 用 10 台或更少的登录服即可满足需求。而当在开新区的时候,或许要配备 40 台登录服才能
应付那如潮水般涌入的玩家登录请求。所以,登录服在设计上应该能满足这种动态增删的需 求,我们可以在任何时候为大区增加或减少登录服的部署。 当然,在这里也不会存在要求添加太多登录服的情况。还是拿开新区的情况来说,即使 新增加登录服满足了玩家登录的请求,游戏世界服的承载能力依然有限,玩家一样只能在排 队系统中等待,或者是进入到游戏世界中导致大家都卡。 另外,当我们在增加或移除登录服的时候不应该需要对游戏世界服有所改动,也不会要 求重启世界服,当然也不应该要求客户端有什么更新或者修改,一切都是在背后自动完成。 最后,有关数据持久化的问题也在这里考虑一下。一般来说,使用现有的商业数据库系 统比自己手工技术先进要明智得多。我们需要持久化的数据有玩家的帐号及密码,玩家创建 的角色相关信息,另外还有一些游戏世界全局共有数据也需要持久化。 好了,需求已经提出来了,现在来考虑如何将其实现。 对于负载均衡来说,已有了成熟的解决方案。一般最常用,也最简单部署的应该是基于 DNS 的负载均衡系统了,其通过在 DNS 中为一个域名配置多个 IP 地址来实现。最新的 DNS 服务已实现了根据服务器系统状态来实现的动态负载均衡,也就是实现了真正意义上的负载 均衡,这样也就有效地解决了当某台登录服当机后,DNS 服务器不能立即做出反应的问题。 当然,如果找不到这样的解决方案,自己从头打造一个也并不难。而且,通过 DNS 来实现的 负载均衡已经包含了所做的修改对登录服及客户端的透明。 而对于数据库的应用,在这种结构下,登录服及游戏世界服都会需要连接数据库。从数 据库服务器的部署上来说,可以将帐号和角色数据都放在一个中心数据库中,也可分为两个 不同的库分别来处理,基到从物理上分到两台不同的服务器上去也行。 但是对于不同的游戏世界来说,其角色及游戏内数据都是互相独立的,所以一般情况下 也就为每个游戏世界单独配备一台数据库服务器,以减轻数据库的压力。所以,整体的服务 器结构应该是一个大区有一台帐号数据库服务器,所有的登录服都连接到这里。而每个游戏 世界都有自己的游戏数据库服务器,只允许本游戏世界内的服务器连接。 最后,我们的服务器结构就像这样: 大区服务器 / | \ / | \ 登录服 1 登录服 2 世界服 1 世界服 2 \ | | |
\ | | | 帐号数据库 DBS DBS 这里既然讨论到了大区及帐号数据库,所以顺带也说一下关于激活大区的概念。wow 中 一共有八个大区,我们想要进入某个大区游戏之前,必须到官网上激活这个区,这是为什么 呢? 一般来说,在各个大区帐号数据库之上还有一个总的帐号数据库,我们可以称它为中心 数据库。比如我们在官网上注册了一个帐号,这时帐号数据是只保存在中心数据库上的。而 当我们要到一区去创建角色开始游戏的时候,在一区的帐号数据库中并没有我们的帐号数 据,所以,我们必须先到官网上做一次激活操作。这个激活的过程也就是从中心库上把我们 的帐号数据拷贝到所要到的大区帐号数据库中。 服务器结构探讨 -- 简单的世界服实现 讨论了这么久我们一直都还没有进入游戏世界服务器内部,现在就让我们来窥探一下里 面的结构吧。 对于现在大多数 MMORPG 来说,游戏服务器要处理的基本逻辑有移动、聊天、技能、物 品、任务和生物等,另外还有地图管理与消息广播来对其他高级功能做支撑。如纵队、好友、 公会、战场和副本等,这些都是通过基本逻辑功能组合或扩展而成。 在所有这些基础逻辑中,与我们要讨论的服务器结构关系最紧密的当属地图管理方式。 决定了地图的管理方式也就决定了我们的服务器结构,我们仍然先从最简单的实现方式开始 说起。 回想一下我们曾战斗过无数个夜晚的暗黑破坏神,整个暗黑的世界被分为了若干个独立 的小地图,当我们在地图间穿越时,一般都要经过一个叫做传送门的装置。世界中有些地图 间虽然在地理上是直接相连的,但我们发现其游戏内部的逻辑却是完全隔离的。可以这样认 为,一块地图就是一个独立的数据处理单元。 既然如此,我们就把每块地图都当作是一台独立的服务器,他提供了在这块地图上游戏 时的所有逻辑功能,至于内部结构如何划分我们暂不理会,先把他当作一个黑盒子吧。 当两个人合作做一件事时,我们可以以对等的关系相互协商着来做,而且一般也都不会 有什么问题。当人数增加到三个时,我们对等的合作关系可能会有些复杂,因为我们每个人
都同时要与另两个人合作协商。正如俗语所说的那样,三个和尚可能会碰到没水喝的情况。 当人数继续增加,情况就变得不那么简单了,我们得需要一个管理者来对我们的工作进行分 工、协调。游戏的地图服务器之间也是这么回事。 一般来说,我们的游戏世界不可能会只有一块或者两块小地图,那顺理成章的,也就需 要一个地图管理者。先称它为游戏世界的中心服务器吧,毕竟是管理者嘛,大家都以它为中 心。 中心服务器主要维护一张地图 ID 到地图服务器地址的映射表。当我们要进入某张地图 时,会从中心服上取得该地图的 IP 和 port 告诉客户端,客户端主动去连接,这样进入他想 要去的游戏地图。在整个游戏过程中,客户端始终只会与一台地图服务器保持连接,当要切 换地图的时候,在获取到新地图的地址后,会先与当前地图断开连接,再进入新的地图,这 样保证玩家数据在服务器上只有一份。 我们来看看结构图是怎样的: 中心服务器 / \ \ / \ \ 登录服 地图 1 地图 2 地图 n \ | / / \ | / / 客户端 很简单,不是吗。但是简单并不表示功能上会有什么损失,简单也更不能表示游戏不能 赚钱。早期不少游戏也确实采用的就是这种简单结构。 服务器结构探讨 -- 继续世界服 都已经看出来了,这种每切换一次地图就要重新连接服务器的方式实在是不够优雅,而 且在实际游戏运营中也发现,地图切换导致的卡号,复制装备等问题非常多,这里完全就是 一个事故多发地段,如何避免这种频繁的连接操作呢? 最直接的方法就是把那个图倒转过来就行了。客户端只需要连接到中心服上,所有到地 图服务器的数据都由中心服来转发。很完美的解决方案,不是吗? 这种结构在实际的部署中也遇到了一些挑战。对于一般的 MMORPG 服务器来说,单台服 务器的承载量平均在 2000 左右,如果你的服务器很不幸地只能带 1000 人,没关系,不少游 戏都是如此;如果你的服务器上跑了 3000 多玩家依然比较流畅,那你可以自豪地告诉你的
策划,多设计些大量消耗服务器资源的玩法吧,比如大型国战、公会战争等。 2000 人,似乎我们的策划朋友们不大愿意接受这个数字。我们将地图服务器分开来原 来也是想将负载分开,以多带些客户端,现在要所有的连接都从中心服上转发,那连接数又 遇到单台服务器的可最大承载量的瓶颈了。 这里有必要再解释下这个数字。我知道,有人一定会说,才带 2000 人,那是你水平不 行,我随便写个 TCP 服务器都可带个五六千连接。问题恰恰在于你是随便写的,而 MMORPG 的服务器是复杂设计的。如果一个演示 socket API 用的 echo 服务器就能满足 MMOG 服务器 的需求,那写服务器该是件多么惬意的事啊。 但我们所遇到的事实是,服务器收到一个移动包后,要向周围所有人广播,而不是 echo 服务器那样简单的回应;服务器在收到一个连接断开通知时要向很多人通知玩家退出事件, 并将该玩家的资料写入数据库,而不是 echo 服务器那样什么都不需要做;服务器在收到一 个物品使用请求包后要做一系列的逻辑判断以检查玩家有没有作弊;服务器上还启动着很多 定时器用来更新游戏世界的各种状态...... 其实这么一比较,我们也看出资源消耗的所在了:服务器上大量的复杂的逻辑处理。再 回过头来看看我们想要实现的结构,我们既想要有一个唯一的入口,使得客户端不用频繁改 变连接,又希望这个唯一入口的负载不会太大,以致于接受不了多少连接。 仔细看一看这个需求,我们想要的仅仅只是一台管理连接的服务器,并不打算让他承担 太多的游戏逻辑。既然如此,那五六千个连接也还有满足我们的要求。至少在现在来说,一 个游戏世界内,也就是一组服务器内同时有五六千个在线的玩家还是件让人很兴奋的事。事 实上,在大多数游戏的大部分时间里,这个数字也是很让人眼红的。 什么?你说梦幻、魔兽还有史先生的那个什么征途远不止这么点人了!噢,我说的是大 多数,是大多数,不包括那些明星。你知道大陆现在有多少游戏在运营吗?或许你又该说, 我们不该在一开始就把自己的目标定的太低!好吧,我们还是先不谈这个。 继续我们的结构讨论。一般来说,我们把这台负责连接管理的服务器称为网关服务器, 因为内部的数据都要通过这个网关才能出去,不过从这台服务器提供的功能来看,称其为反 向代理服务器可能更合适。我们也不在这个名字上纠缠了,就按大家通用的叫法,还是称他 为网关服务器吧。 网关之后的结构我们依然可以采用之前描述的方案,只是,似乎并没有必要为每一个地 图都开一个独立的监听端口了。我们可以试着对地图进行一些划分,由一个 Master Server 来管理一些更小的 Zone Server,玩家通过网关连接到 Master Server 上,而实际与地图有
关的逻辑是分派给更小的 Zone Server 去处理。 最后的结构看起来大概是这样的: Zone Server Zone Server \ / \ / Master Server Master Server / \ / / \ / Gateway Server \ / | \ \ / | \ \ / | Center Server | | Client 服务器结构探讨 -- 最终的结构 如果我们就此打住,可能马上就会有人要嗤之以鼻了,就这点古董级的技术也敢出来
现。好吧,我们还是把之前留下的问题拿出来解决掉吧。 一般来说,当某一部分能力达不到我们的要求时,最简单的解决方法就是在此多投入一 点资源。既然想要更多的连接数,那就再加一台网关服务器吧。新增加了网关服后需要在大 区服上做相应的支持,或者再简单点,有一台主要的网关服,当其负载较高时,主动将新到 达的连接重定向到其他网关服上。 而对于游戏服来说,有一台还是多台网关服是没有什么区别的。每个代表客户端玩家的 对象内部都保留一个代表其连接的对象,消息广播时要求每个玩家对象使用自己的连接对象 发送数据即可,至于连接是在什么地方,那是完全透明的。当然,这只是一种简单的实现, 也是普通使用的一种方案,如果后期想对消息广播做一些优化的话,那可能才需要多考虑一 下。 既然说到了优化,我们也稍稍考虑一下现在结构下可能采用的优化方案。 首先是当前的 Zone Server 要做的事情太多了,以至于他都处理不了多少连接。这其中 最消耗系统资源的当属生物的 AI 处理了,尤其是那些复杂的寻路算法,所以我们可以考虑 把这部分 AI 逻辑独立出来,由一台单独的 AI 服务器来承担。 然后,我们可以试着把一些与地图数据无关的公共逻辑放到 Master Server 上去实现, 这样 Zone Server 上只保留了与地图数据紧密相关的逻辑,如生物管理,玩家移动和状态更 新等。 还有聊天处理逻辑,这部分与游戏逻辑没有任何关联,我们也完全可以将其独立出来, 放到一台单独的聊天服务器上去实现。 最后是数据库了,为了减轻数据库的压力,提高数据请求的响应速度,我们可以在数据 库之前建立一个数据库缓存服务器,将一些常用数据缓存在此,服务器与数据库的通信都要 通过这台服务器进行代理。缓存的数据会定时的写入到后台数据库中。 好了,做完这些优化我们的服务器结构大体也就定的差不多了,暂且也不再继续深入, 更细化的内容等到各个部分实现的时候再探讨。 好比我们去看一场晚会,舞台上演员们按着预定的节目单有序地上演着,但这就是整场 晚会的全部吗?显然不止,在幕后还有太多太多的人在忙碌着,甚至在晚会前和晚会后都 有。我们的游戏服务器也如此。 在之前描述的部分就如同舞台上的演员,是我们能直接看到的,幕后的工作人员我们也 来认识一下。 现实中有警察来维护秩序,游戏中也如此,这就是我们常说的 GM。GM 可以采用跟普通
分享到:
收藏