场景型网游服务器架构设计

本文所讨论的只是现有网游中一部分会采用这种架构思想,但自己,网游种类不少,因此须要专门对当前网游的需求进行一系列改变,因此本文不表明全部网游服务器架构。算法

 

对于网游的服务器架构设计,咱们主要考虑下列几个点:数据库

1,游戏类型:现有的游戏类型有不少,有房间式、世界类型、场景型(跟房间类型有部分相同)设计模式

2,链接方式:大部分游戏采用TCP长链接方式,但有些游戏也采用UDP传输或TCP/UDP共用缓存

3,在线人数:为了保证游戏的流畅性,咱们必须确保服务器集群的容灾和扩容性,以便于防止同时在线人数的增长。安全

4,性能方面:主要考虑内存、CPU、宽带等物理问题。服务器

 

本文主要说明一类场景型网游服务器架构的设计框架。网络

首先咱们理解一个网游服务器在游戏中所扮演的角色,咱们能够把它理解为一个上帝角色,它拥有当前场景下全部玩家、NPC、事物对象的各种属性(状态、动做)的一个读写权,它能够经过自身的逻辑处理,将多个客户端链接到一块儿,呈现一个“统一”的世界。多线程

下面先介绍一款游戏(刀剑Online,参考了网上其余大神的Blog)的服务器架构:架构

1,链接负载服务器(Connection Load Server - CLS)负载均衡

  CLS主要负责服务器端与客户端的网络链接,主要做用就是将真正的服务器端口与客户端隔离开,CLS进行网络链接的处理,信息交互的处理,错误数据的处理......,有了CLS层后,咱们能够有效的下降了逻辑层的负担,同时保证逻辑层对于客户端彻底是一个黑盒服务器,确保其安全性,还有即是TCP长连问题,咱们不须要再对TCP的链接进行处理,若是更换场景时,仅须要服务器端进行一个场景服务器的切换而已,TCP端口并不须要断开重连。通常咱们只在CLS层进行网络数据的交互,关于游戏逻辑层的处理,是彻底交给下层服务器处理,主要是为了保证框架的理解性,使得整个框架更加清晰。

  在编写CLS层的代码时,咱们须要注意一些细节:

  ⑴,对于游戏服务器的逻辑处理,咱们为了保证游戏的流畅性,就必须保证网络通信作到及时处理,而TCP协议中,默认会开启Nagle算法,此算法的设计理念是在早期,若不断进行一个字节数据包的传输,TCP传输的有效利用率就会大大下降,大部分的CPU资源会浪费在TCP传输包的处理上,对于一些负载较重的网络,很容易形成拥堵,而Nagle算法就是在发送端欲发送屡次少许数据包时,会先将第一个数据包发出去,其余小的数据包会先进行缓存,只到第一个数据包的ACK返回时,才会把缓存的包发出去,这样能够有效下降TCP传输中的资源浪费,但对于游戏中,这种作法是很难接受的,因此咱们就须要关闭这个算法,在链接时使用TCP_NODELAY参数,禁用Nagle算法。

  ⑵,链接负载服务器组在与客户端进行交互以前,还必须先进行网络链接,若是仅仅只是一个1W人同时在线的小型游戏,那基本不须要多考虑,直接一台服务器进行链接交互就能够,但若是人数过大,一台服务器根本没法负担起这个工做,就须要一个服务器组,其前段再有一个负载均衡器对客户端的链接进行分配就能够

  ⑶,链接负载服务器对客户端发过来的数据如何进行解密,现有两种作法,一种是部分解密,一种是彻底解密,具体参照上述说CLS层最好不要作过多其余层的东西,那一样逻辑层最好接受到的信息,也是不须要解密的明文类型,因此我的建议是在CLS层对数据包进行彻底解密,再传输给逻辑层进行处理。

 

2,总控服务器(Master Server - MS)

  总控服务器有管理当前全部游戏相关内容的全向,好比某个客户端的登陆、注销、角色操做、不一样场景间的互动均由总控服务器处理,MS须要与其余的场景服务器时刻保持链接,咱们能够把MS想象成一个服务器的中枢,它先从CLS层取得数据包,而后根据是否须要场景服务器处理判断后,若是不须要,自身处理完将结果反馈给CLS,若是须要,则分配给专门的某个场景服务器进行处理,并通知CLS层,让后续该用户的指令均直接转给该场景服务器处理。以其工做场景举个例子:

  ⑴,用户A与B分别处于不一样场景服务器的管理上,A与B沟通时,则须要A的场景服务器将信息包发送给MS,包中有用户B的基础信息,MS会在临时管理信息库中进行检索,找到B的信息后,将该信息包再次发送给B所属的场景服务器。

  ⑵,用户A处于场景服务器1中的传送点,要传送到场景服务器2管理的场景,则会发送指令给MS,由MS给场景服务器2发送接收指令,这时便有MS对用户A进行服务器信息的更换,将用户A的信息处理放置在场景服务器2中。

 

3,场景服务器(Zone Server - ZS)

  场景服务器主要负责当前场景下的全部玩家的指令交互和逻辑处理,通常一个场景服务器所能同时支撑的在线人数在10000人左右,若是超过就会严重影响玩家的使用,因此对于一个玩家很是多的游戏,都会采用一种逆向管理发,以玩家ip进行服务器的分配,而再也不是场景(固然,对于如今的场景型网游,通常不多出现一个场景下万人在线)。

  对于场景服务器,通常必须的要求有:1,高效(解决方法就是尽量提高效率和代码的优化,并使用高效的脚本语言)

2,灾难回复机制,当ZS发生非法操做致使影响某段时间用户的数据,就必需要保证没隔一段时间就对数据进行一次存储,这样的代价就是大你们中了对数据库方面的负担(但没有办法,必须的),而有些游戏的作法就是将某些关键数据放在程序的共享内存中,这样就算发生数据非法访问等,也能够在重启时,直接从共享内存中对数据进行回复,同时恢复时必须对数据进行校验,防止将错误的数据存入数据库。

 

上述大体描述了一个场景型网游服务器的架构设计,那还有一些细节,好比每一个玩家的完整信息存放在哪里之类的,玩家对象和场景的关系等等。下面一一分析一下。

4,玩家对象

  服务端若是须要对玩家进行逻辑处理,那就必然须要对每一个玩家构建一个对象,以确保处理的对象不会发生错乱,那这个对象咱们放在哪里会比较好一些,CLS?MS?ZS。

  首先讨论讨论一下CLS,咱们前面说过,CLS的做用仅仅只是一个链接负载的做用,仅仅对客户端的链接进行网络交互和发给逻辑层处理,不作任何逻辑判断和内存处理。因此先PASS,那确定是须要放在逻辑层的。

  其次若是把玩家对象放在MS上,那全部的玩家都会在MS的内存中保留一份数据信息,好处就是对象统一性,能够在MS中直接对玩家对象的一些信息进行处理,好比玩家之间沟通,但这无疑加大了MS的内存压力,同时若是MS接受到一些非法操做信息,有可能就会延迟整个服务器的玩家,甚至掉线。最后举个最麻烦的例子:假如玩家A在场景1下与怪物PK,因为对血量数据的记录是放在MS中,那也就是说ZS必须先对数据进行处理,而后发送给MS进行保存,MS进行统计完后给ZS发送ACK,最后再由ZS反馈给客户端,这个过程无疑有些麻烦了。

  那最后再考虑一下将玩家对象放置在ZS中,这种状况将对象放在ZS中,好处就是,在ZS中,咱们不管进行什么操做,ZS均可以直接获取对象信息,在场景内的交互是很是便利的,不须要多余的数据传输,只是跨场景操做才须要经过MS中转一下数据。但也有一些缺点,好比全部的对象信息,就须要同时在ZS、MS、数据库中进行同步,假如咱们须要进行屡次跨服操做,一样就须要将数据从ZS中提取,传输到MS中进行逻辑操做,操做过程当中ZS是不能修改当前对象的相关信息。这样无疑也是很麻烦的,因此不管放在ZS或这MS上,都是有必定的弊病,须要根据游戏的具体情景进行分析放置。

 

5,玩家对象和世界对象的模式关系

  ⑴,玩家自我操做模式:

  好比玩家使用某个做用对象为本身的物品-加血,流程大体就是服务器中获取对应的玩家对象,对自身加锁后,进行处理血量数据的添加,处理完后解锁,将处理的信息再次反馈给客户端显示血量添加。这种自我操做模式不须要考虑其余对象,仅仅对当前进行操做的对象进行加锁-处理-解锁便可,但若是是互动模式,就不能对别的对象进行加锁操做,不然二者有可能陷入死锁。那在互动模式下,服务器的操做流程是怎样呢?看一个图:

上图能够看到,若是对象A对对象B发起进攻,服务器接受到该指令后,须要与B交互,则将该消息打包放入一个消息队列中,并指定接受者为对象B,服务器会不断检索消息队列,发现有消息时,就会取出开始执行相应操做,流程与自我操做模式类似,为B上锁,减血后,解锁。通常游戏的服务器设计中,玩家与玩家之间的交互都是经过消息传递交互的。

  这种设计模式的优缺点也是比较明显的:优势就是在开发人员实现具体的逻辑时,咱们不用担忧加锁解锁的问题,咱们只须要对消息进行逻辑处理而且对客户端进行反馈就能够,同时每一个对象都不能直接对其余对象进行操做,放置死锁等现象,但缺点就是频繁的消息传递,增长交流的成本,两个对象之间没法直接获取对方的属性,必须经过消息传递,致使逻辑处理会延后,当在线人数太高的状况下,有可能会形成一些错误、超时等等。

  ⑵,世界型上帝模式:

  以一个例子来讲明:玩家A向玩家B发起攻击

  流程图中能够看出,服务器分别找到A,B两个对象,将二者锁住后,直接由服务器进行攻击的逻辑操做,这里服务器就是一个能够访问全部对象属性的管理者,这样作的危险型就是容易发生死锁,因为是对多个对象进行加锁,那多线程下,两个对象相互攻击,那就有可能产生死锁的状况,因此在进行加锁前,必须对id先进行排序,保证了加锁的对象不会产生重复。这种模式的优势就是逻辑的编写是比较简单的,直接对多个不一样的对象进行逻辑操做就能够,但有可能致使过多加锁的冲突和等待,就须要设计人员对总体的框架有着良好的规划和加锁策略。

 

上述就是本文关于场景型网游服务器设计架构的一个简单的分析理解,本文只是简单的走了一遍服务器架构的思想,但具体编码的不少细节还须要在具体项目中去探索。

相关文章
相关标签/搜索