【转】服务器结构探讨 -- 简单的世界服实现

转自 http://blog.csdn.net/lfhfut/article/details/1779848

  讨论了这么久我们一直都还没有进入游戏世界服务器内部,现在就让我们来窥探一下里面的结构吧。

  对于现在大多数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 

 

 

posted @ 2017-11-22 10:43  colourstar  阅读(275)  评论(0编辑  收藏  举报