嘉宾简介

刘强

刘强 百万在线的基石――梦幻手游服务器架构

梦幻事业部高级技术总监及软件设计专家。04年至13年,担任《梦幻西游》端游服务端主程,2014年至今,担任《梦幻西游》手游主程。

分享内容

摘要

  说到手游中的重度游戏MMO,如何提供一个稳定高效的手游MMO服务器引擎?梦幻西游手游如何做到万人同时在线?手游和端游在MMO上有何不同?AOI如何实现?通过什么样的开发流程就可以保证在产品上线时稳定,不会出现大面积DOWN机的情况? 一整套解决方案,你值得拥有。

  “我们引擎是多线程的结构,分线程的理由,首先模块比较独立,然后很好分,虽然我们采用多线程引擎,但是开发思路上用单线程来开发,所以并没有损失我们的开发效率。”

文字实录

百万在线的基石――梦幻手游服务器架构

1/29
  • 百万在线的基石――梦幻手游服务器架构
       大家好,我是刘强,也可以叫我"强宝"。

      随着手游越发端游化和重度化,衡量一款手游的数据除了传统的留存率、ARPU等外,还新增了PCU(Peak concurrent users ,既最高同时在线玩家人数)等数据。但是同时多人在线对服务器的运算能力和稳定性都有着极大的要求。在此次的网易游戏学院上,《梦幻西游》手游的主程刘强,就《梦幻西游》手游中如何做到200万人同时在线,如何提供一个稳定高效的MMO手游服务器引擎等问题发表了演讲。

      
  • 百万在线的基石――梦幻手游服务器架构
       有人问我说,为什么大家都讨论客户端技术,服务器端的技术没有人讨论?好像是这么回事,第一眼美女,大家比较关注,但服务端同样重要。所以我给大家介绍一下《梦幻西游》手游架构是什么,以及为了保证架构比较稳定,我们又做了哪些努力。

      
  • 百万在线的基石――梦幻手游服务器架构
       这是我今天介绍的一些主要内容。

      
  • 百万在线的基石――梦幻手游服务器架构
       这是我们获得的一些成绩(见图),首先获得苹果优秀新游戏的推荐,大概上线三四天左右,我们获得了iPhone和iPad四榜第一,这是整个网易游戏的荣耀,我们是中国第一家拥有苹果开发者的公司。当中的海报是我们获得注册玩家突破2千万,以及同时在线200万时期制作的。

      
  • 百万在线的基石――梦幻手游服务器架构
       服务器架构。

      
  • 百万在线的基石――梦幻手游服务器架构
       服务器架构,我们手游引擎大概是怎样的水准?我们的引擎来于梦幻端游,大概2.2万单服架构,手游引擎稍微差一点,1.5万,但是我们还是有比较大的优化空间。据我了解,在市面上手游单服架构里还没有过万的手游引擎,当然除了我们。

      
  • 百万在线的基石――梦幻手游服务器架构
       这是我们服务器架构,主要分几块,有gameserver、loginserver、webserver、centerserver。首先是loginserver,loginserver访问了以后,进行一些帐号的验证,然后根据验证后获得的列表,然后开始访问Gameserver,Gameserver自己跟所验证的server进行验证,这样就保证了我们loginserver可以无限增加的。当时考虑loginserver可能会负载高,所以设计成这种架构。然后Weberver顾名思义,就是一些gm、voice用的,因为我们提供语音聊天和语音转文字服务,这应该是社交类游戏的神器,一定要提供。Centerserver就是提供全服玩法的活动。

      
  • 百万在线的基石――梦幻手游服务器架构
       引擎线程结构,我们引擎是多线程的结构,分线程的理由,首先模块比较独立,然后很好分。虽然我们多线程引擎,但是开发时用单线程的开发思路,所以并没有影响我们的开发效率。

      
  • 百万在线的基石――梦幻手游服务器架构
       我们大部分是一些IO和CPU密集型的线程脱离,主线程主要是游戏逻辑,这也是一些基础模块,就是我们分为引擎和脚本,脚本里主要跑逻辑,引擎里主要是跑基础模块,像玩家登陆,还有就是CPU密集型的东西,放在脚本里比较合适。

      
  • 百万在线的基石――梦幻手游服务器架构
       aoi的实现。

      
  • 百万在线的基石――梦幻手游服务器架构
       手游和端游AOI有明显的区别,有两种算法,一种九宫格算法,插入和删除节点,速度非常快,属于O(1)。但是有一个很大的问题,就是当它在格子间移动时有大量的带宽消耗,因为有很多无用的信息在发送。十字链表,移动时是很省带宽的,但是在长距离时,它的CPU是消耗非常大的,这两种我们网易这边都有实现,都尝试过,也对它们比较了解。

      
  • 百万在线的基石――梦幻手游服务器架构
       MMO的手游AOI有什么特点?更多的传送,都是属于直接传送到地图中间,比较少的走路。客户端受制于硬件,同屏显示人数有限,不像端游,可以随便显示很多,这样需要显示人数减少,否则手机会卡死。NPC视野类的玩法很少,基本可以忽略。就是说十字链表在做NPC视野的玩法是非常好的,所有的NPC可以选择不同视野范围,但是我们手游基本上这种玩法不考虑,因为没有嘛,所以我们选用格子。

      
  • 百万在线的基石――梦幻手游服务器架构
       这是我们开发到中期时,然后在做1万人压测时的效果,这些全是机器人,他们在里面还是走路。

      
  • 百万在线的基石――梦幻手游服务器架构
       这是我们做不删档测试第一天的时候,因为没有放AOI优化的效果图,这是真实的玩家,就是相当于万人以上的,大概效果是这样的,和压测的效果是一样的,都是满满的人,所以整个世界上都充斥着各种"吐槽"的话,所以玩家体会很糟糕,因为客户端卡,手机上显示这么多角色是非常糟糕的一种表现。

      
  • 百万在线的基石――梦幻手游服务器架构
       鉴于这种,我们设计了一个分层AOI概念,不同的玩家,还有不同的组队信息,以及好友有一个很复杂的规则,把玩家分在不同的层次,还有就是当人数增多,可以动态进行分层,人数少的时候可以把层数合并回来,然后就是让玩家在人少的时候也能看到几个人,人多的时候还是看到几个人。这种优化放过来后,这是同一台服务器,效果大概是这样的,你在同一层里看到的都是你关心的人。这个感受就很好了。

      
  • 百万在线的基石――梦幻手游服务器架构
       一些基础模块的实现。基础模块我们这边主要分为三块:udb、行为树、语音。

      
  • 百万在线的基石――梦幻手游服务器架构
       为什么要设计一个udb,udb有做统一的管理,在定时存盘+退出存盘,经典解决存盘的模式,有一种性能瓶颈,当你的同服玩家最高在线没有很高时,是不会遇到这个瓶颈的。在定时存盘时,同时想让一万以上玩家做存盘,这时候序列化会很卡,很耗CPU,并且有down机回档的问题,有一些人已经退出存盘,但是另一些人在等待定时存盘,当down机,两个人的db是不一致的,所以这很多运营上的问题。运营又给我们提了一个需求,玩家数据备份能不能随时随刻到任意一点,因为我要拿到那一点玩家的数据进行处理。我们现在UDB可以支持这个了。还有一个硬件条件,现在64位机器内存足够大,可以缓存一周所有登陆的玩家。

      
  • 百万在线的基石――梦幻手游服务器架构
      这是我们设计udb的一些理念,采用NoSql的理念,用binlog记录kv变化。我们某个备份+binlog可以恢复到任意一时刻的备份,方便运维查证处理问题。如果这时候服务器crash了,可以根据binlog恢复所有db到down机那一刻的状态,实现O回档。当然除了正在down机时那一秒,有可能有一些没有写下来。备份时非常方便,把binlog rotate一下,然后本地或者远程备份下即可。以前需要把所有变化的db抽出来,打成一个包,再放到远程,这就很麻烦。这是Lru算法管理的方法,因为我们缓存有一个数量,相当于一个缓存池,64位机器内存已经足够缓存一周登陆过的db了,所以可以集中管理DB,通过Lru算法调整db数量。

      
  • 百万在线的基石――梦幻手游服务器架构
       AI行为树,因为我们是回合制战斗,所以AI行为树非常适合我们。我们为什么要选择AI行为树。因为非数值策划也可以很容易学会写AI,说起来很容易,如果不使用行为树是很难的,我们现在连文案策划也可以写一些简单的AI。当时项目情况,在有一个端游或者有一个竞品参考时,策划工作稍微小一些,但是程序开发量很大,所以把所有能分给策划写表或者填图的都分给策划做,这样分工合作才能整体提升团队的工作效率。

      
  • 百万在线的基石――梦幻手游服务器架构
       这是我们的一个AI行为树的工具图,有四到五种节点,就很直观的先干什么,再干什么,添了这个后,所有的AI全部搞定了,所以程序基本上不关心战斗了。

      
  • 百万在线的基石――梦幻手游服务器架构
       后来我们做一些统计,现在我们基本上所有战斗采用行为树,在所有战斗消耗的CPU里,大概超过50%消耗在行为树上,目前我们的战斗还没有遇到瓶颈。

      
  • 百万在线的基石――梦幻手游服务器架构
       如何优化引擎和提升引擎的健壮性。

      
  • 百万在线的基石――梦幻手游服务器架构
       我们的针对手游改造后,怎么提升引擎健壮性,主要是从以下几方面考虑。

      
  • 百万在线的基石――梦幻手游服务器架构
       首先内存,你的引擎稳定,内存越界写,内存泄漏是必须要清掉的。valgrind神器,脚本虚拟机需要有统计object的数量,每个object的大小,array、table等都有总的大小统计。

      
  • 百万在线的基石――梦幻手游服务器架构
       IO与CPU,基本上是一个循环优化的过程,优化了CPU,下一个发现卡的时候就是IO,再优化完IO,又卡到CPU了,是一个循环过程。我们做的这方面的工作,上线前要预估自己的热点是哪里,我们就很好预估,首先登陆,走路、战斗,这是预估可能出现的热点,我们就做压测,先5000人,拼命的干同一件事。压测的效果乘1.5到2倍,假设5000人压测了,基本上1万人也没有大问题。另外就是分别做引擎和脚本的profile,找出引擎和脚本的热点,热点简化,脚本热点可以引擎化。脚本做profile的不多,可以考虑在虚拟机调用函数的时候来做profile统计。这是很准的,定位到函数领域时,基本上你的热点也找到了,这是解决脚本的一个神器。

      
  • 百万在线的基石――梦幻手游服务器架构
       IO,实际是一个很大的问题,我们效果最好的一个解决方法,就是多线程的异步写,解决顿卡的超神器,基本上同步读了一个IO导致的,所以我们现在正常的IO都属于异步的,LOG属于异步写的,数据文件存在异步写。需要读数据时,该函数挂起,等到子线程读好数据后再回调该函数。这是我们一个很简单的例子,因为是一个异步,要注意所有的条件检测,为什么要到原函数,因为函数里有一些条件检测,如果不是直接回到原函数,有可能有一些条件检测会被跳过,这时候可能出现逻辑上的问题。还有就是查IO,我们在优化的过程中会发现,基本上引擎本身的问题是很少的,大部分都是大家写代码的时候写得不够规范,或者是有其他的问题。

      
  • 百万在线的基石――梦幻手游服务器架构
       IO,实际是一个很大的问题,我们效果最好的一个解决方法,就是多线程的异步写,解决顿卡的超神器,基本上同步读了一个IO导致的,所以我们现在正常的IO都属于异步的,LOG属于异步写的,数据文件存在异步写。需要读数据时,该函数挂起,等到子线程读好数据后再回调该函数。这是我们一个很简单的例子,因为是一个异步,要注意所有的条件检测,为什么要到原函数,因为函数里有一些条件检测,如果不是直接回到原函数,有可能有一些条件检测会被跳过,这时候可能出现逻辑上的问题。还有就是查IO,我们在优化的过程中会发现,基本上引擎本身的问题是很少的,大部分都是大家写代码的时候写得不够规范,或者是有其他的问题。

      
  • 百万在线的基石――梦幻手游服务器架构
       延时,所有游戏玩家的感受,游戏这种交互感受主要依赖于服务器返回速度,所以基本上可以建立延时统计系统,比如说玩家协议过来,开始记录时间,然后给他进行了回复,记录一个时间,记录两条协议执行的时间。以回合制游戏为例,0.5S以下服务器延时,玩家感觉是非常流畅的,没有任何卡顿的感觉,如果2-3秒的延时,玩家有很明显的卡顿感。所以控制平时要在0.5S内,活动尽量控制2S内,感受就比较好。前面是介绍一些我们引擎的一些相关东西,后面就介绍为这些引擎提供的流程上的帮忙,协助保持引擎稳定性。

      
  • 百万在线的基石――梦幻手游服务器架构
       流程上可以提供什么助力?

      
  • 百万在线的基石――梦幻手游服务器架构
       codereview,对解决低级bug有非常好的效果,一种强限制型的,还有一种弱限制型的codereview,要选择一个适合你自己项目的方式。还有平衡工作量带来的影响,我们项目初期绝对不需要Review的,因为大量的代码,还在堆量,是没有时间做Review的,当项目进中后期才可以考虑开始做这个事情。强限制型有打断的问题,我的工作必须给另一个人看完,我才能提交,所以这种限制性比较强。弱限制型,我提交完,让Boss看,看完有问题我再改,我们是采用弱限制型,但是这也不一定,就看自己的项目,采取适合自己项目的情况就好了。

      
  • 百万在线的基石――梦幻手游服务器架构
       这是我们review的一个截图。Review Board是一种开源的软件,可以直接搭建一个,直接在上面看代码,做deffer 的对比,很方便。

      
  • 百万在线的基石――梦幻手游服务器架构
      而且你也可以通过这工具进行一些统计,比如严重bug、代码风格的问题,你也可以了解一个月的获利情况。发现的严重bug都是对你的项目损害非常大的,而这些都是可以通过流程上去避免的。

      
  • 百万在线的基石――梦幻手游服务器架构
       代码覆盖率,主要就是保证QC的测试用例写得足够全面,当我写了一篇代码后,让QC测,我并不知道所有的代码所有代码逻辑全都跑过了。

      
  • 百万在线的基石――梦幻手游服务器架构
       内容页面的一个截图,每个内容会建一个项目。

      
  • 百万在线的基石――梦幻手游服务器架构
       比如说我这个没有跑到,所有我修改的函数会被标注"未运行",并且这里用例缺少了,所以就要针对这个再写一些用例进行回归,把这些覆盖到,主要是协助QC用的。

      
  • 百万在线的基石――梦幻手游服务器架构
       静态代码检测,因为有一些东西跑不到,主要是为了查找是否有笔误,调用不存在的函数,或者调用的参数不符合要求。因为有一些参数写错了,编译又不报错,但是你放给外服后才开始报错。

      
  • 百万在线的基石――梦幻手游服务器架构
       这是静态代码检测的一个截图,主要是调用一些不存在的函数,大部分是字母写错了。

      
  • 百万在线的基石――梦幻手游服务器架构
       自动化回归,为了保证前人种树、后人乘凉,这是一个积累的过程,每次放出版本前进行脚本自动回归,保证已有的东西没有问题,新增内容不会影响到已有内容。

      
  • 百万在线的基石――梦幻手游服务器架构
       这是我们自动化回归脚本的一个例子, 就是说它会自动跑多少个脚本,现在已经运行完多少个,继续跑,当某一个脚本出现问题,不符合预期结果的时候会中断掉,并且把它的结果打印出来,这里基本上每周跑一次,就很放心了。

      
  • 百万在线的基石――梦幻手游服务器架构
       协议测试,这是很重要的,所有的协议必须让QC做一遍,他来设计数值,发送给服务端,测试服务端健康性。尤其手游开发,经常一个人服务端、客户端都做,这样就很容易信任自己客户端传来的数据。当你新写一个游戏后,一定有好几个地方是这样,然后一定会被玩家刷爆。我们最后把所有的协议函数,让程序员排查了一遍,是不是所有协议参数都进行了合法性测试,所以这个检测是最重要的。

      
  • 百万在线的基石――梦幻手游服务器架构
       我的内容就这么多,谢谢。

      
关闭