游戏网游新开服务器器有哪些特别之处功能

听云APMCon: MMO游戏服务器性能监控及优化
听云APMCon: MMO游戏服务器性能监控及优化
中国应用性能管理行业盛宴――2016中国应用性能管理大会(简称APMCon 2016)于8月18日至19日在北京新云南皇冠假日酒店隆重召开。APMCon由听云、极客邦和InfoQ联合主办的作为国内APM领域最具影响力的技术大会,首次举办的APMCon以“驱动应用架构优化与创新”为主题,致力于推动APM在国内的成长与发展。
原博瑞游戏CTO田博辉于服务端应用监控实践发表了题为《MMO游戏服务器性能监控及优化分享》的演讲,现场从游戏服务器架构演变,预警体系,实时分析系统,游戏优化手段等方面分享一些踏过的坑。
以下为演讲实录:
大家好!我个人做了十多年的游戏,现在准备去创业了,可能会暂时离开游戏圈或者说技术圈,在这之前借着这个大会,我把我十多年肚子里的东西都给大家掏出来,给大家分享一下。
咱们这里做游戏的多吗?我估计是不多,所以我就想今天主要是把游戏性能的思想给大家介绍一下。2010年之前游戏行业的性能比互联网要好得多,但是2010年之后移动互联网和互联网发展特别快,包括分布式、一些容器的发展,那时候游戏就进入瓶颈期了,原因很简单,用户量下来了。当时我做游戏的时候我们一个星期用户注册量在500万都是很正常的值,现在一个生命周期都不到一百万了。

这是一个游戏的架构,可能大家会说我不是做游戏的,这个架构跟我没有关系,其实它和互联网是一样的。非常简单,这个是用户,然后用户先连到战区列表服务器,就相当于一个CDN,相当于一个做分布式的服务器,后面是DB的集群。后面这里是一个网关服务器,网关服务器是做网络转发、网络安全的,包括一些用户状态的验证,相当于咱们应用的登录服务器。它的整体架构和互联网是没有太大差别的,比如咱们游戏服务器后面是一个组,这个组就相当于网站的业务服务器,我认为总体思想和互联网没有多大区别。这里有一句话是我十多年的感悟,就是架构和业务是相互促进的,比如说我这里能够支持20万人实时在线,也就是说会有100万的活跃用户,500万的注册用户,这是一个区,如果多了怎么办?那就用分布式,然后后面跟了很多log服务,log服务是我今天讲的主要重点。

这是运营系统架构,它的核心比较简单就是搜集log,把所有的log聚集起来通过一个数据仓库的概念分策略来走不同的部门,包括运维、研发,不同的权限去看到不同的内容,这是游戏里面用的比较多的,包括它在不同层次的实时数据,有一些数据我们要实时看,比如现在多少人在线,后面就是采集数据,比如说玩家今天进行某些操作多少次,比如我今天去找别人交流多少次,别人同意了多少次,不同意多少次。这个就是数据的分析,现在的玩家都有语音聊天,说今天语音聊天多少次,打字多少次,为什么语音多,打字多?这个都能分析出来,然后是游戏的同步数据库,后面分到不同的部门去,比如说运维、运营,有不同的权限可以看。
这个是前天晚上临时加上的比较糙,但是这确实是一个监控系统,它是怎么做的?它在每一个服务器有一个自我健康信息的汇报系统,就是把我服务器的健康情况汇报给最后的中心控制服务器,这里面有一些策略,有一些阀值的设定,比如说阀值大了就要报警,可能报给运维系统或者运营系统,为什么是两个?运维系统是管硬件,运营系统是管业务型的,它是有一些权限分配的。
关于硬件的监控项,我就说和互联网没什么区别吧,就是监控CPU,监控内存、硬盘、磁盘IO、外网内网的网卡使用率,这和互联网一样的。
这是我们的一个监控报表,这个表主要就是分析波峰这个地方的问题,包括CPU、内存,这是我前两天让运维系统截的图,这个图是在服务器维护的时候截的基本上没有负荷的图,这个地方很简单,估计就是服务器刚启动的时候。
这是软件监控项,这个就和游戏业务关联比较紧密了,我说的一句话是这样的,监控的东西绝对是业务上的关键点,你的业务哪一点最关键肯定要监控它,比如说我这边要监控帧速率,还有网络连接数目,因为当时做游戏还是有很多竞争对手,或者有一些大学生朋友会用一些所谓的黑客手段来悄悄的试一下你的服务器,他会疯狂的连接你,然后疯狂的给你发包,这个时候会有一些安全的设定,包括线程的状态、数据库状态,这个确实是和我们的业务紧密相关的。还有在线玩家数量都是和业务相关的,包括NPC的数量等等,这主要是一种思想。
不同的监控有不同的手段,我有一些朋友也是专门做监控来创业,他用一些手段做一些数据最后进行汇总,汇总就是记录日志或者各类报警,这里面可以用开源工具、内嵌API或者心跳等各种方式来实现,但是每个公司有自己擅长的方式或者他用得习惯的方式,这个东西是不能统一的,或者你用哪个熟悉就用哪个,目的达到就可以了,我是这么认为的。
我慢慢接触到业务的东西会多一点,监测和分析是基于业务的,你要做的东西是不是靠谱?上线之后它的效率怎么样?是不是有log记录?是不是有分析?肯定都是基于业务的。比如刚才讲的帧速率,现在咱们讲一下房间数目,或者说一个好玩一点的,咱们讲个NPC的数量,就是怪的数量,每一个怪有一个自己大脑的一个类,然后来跑里面的一些功能,当这个怪的数量足够多的时候会把服务器干掉。
当时我们有一个新来的小同事,因为我们的房间是定期释放的,他没有释放这个房间同时也没有释放怪,然后晚上两点多的时候就接到报警了,房间数目超过一千个,怪超过三万。当时帧速率开始没有怎么掉,没有掉的原因是我们做了一个优化,我们的优化是激活对象的数量,虽然怪没有释放但是这个状态是不激活的,因为没有人没有玩家,不激活基本上就不跑逻辑,所以虽然内存飙上来了但是帧速率没有掉,这个可能是当时的一个优化方式造成的一个血淋淋的教训。
再比如说在线玩家数量,现在有好多游戏上线之后可以看到有好多人,那个东西是怎么弄的呢?这个是行业内幕,好多时候是积分墙还有机器人压上去的,但是有一种情况叫做假用户,就是各种bug造成的,你下线之后那个玩家还存在于服务器上面,可能就是咱们做网站的时候链接没有断掉之类的。
还有存档状态,存档是最要命的东西,有一次我们在做活动的时候,有一个玩家充值充了12万左右去冲排行榜拿武器,充完值后非常不幸掉档了,玩家就来到我们公司找我们。所以,后来我们把存档单独独立出来,做了一个存档服务器。当然现在游戏经过了大概小20年的发展,这些东西都已经成形了,这个东西在2010年左右我们已经做过了,现在都2016年了,我就感觉游戏行业在技术方面的突破已经特别少了,最多就是把DB换掉,我感觉好像也没有多大意思,原因比较简单,它的用户量已经没有那么多了。
这是一个我们内部使用的简单的监控。这是一个游戏刚启动,立项维护的时候,没有太多的内部数据,它里面就是记录了一些核心的东西,比如说帧速率、在线、登录状态,就是记录这些东西和关键的核心业务。
这里会有详细的记录,比如说刚才的服务器出现问题之后,我们双击进来看到它更详细的信息,比如这个包有多少人,帧速率是多少,详细的数据分析,然后下面它还能再点进来,比如常见IP,有多少房间,房间里面有多少人,你所关注的业务的特别核心的地方都把它监控出来,当你用得到的时候就会用到。
下面我们讲优化,基本上监控完了之后肯定是要优化的,优化可能牵一发而动全身,尽快利用各种手段解决问题,保证项目运行,尤其是上线的项目。大家听完了演讲之后可能都热血澎湃,回去之后我要优化我们的系统,然后回去优化了两条代码发现系统和你想象的不一样了,确实是这样的。
举个例子,当时杭州我们有一个工作室,杭州的工作室做了一款项目,他们DB设计的有问题,之后他们核服的时候核一个服可能需要大概30多个小时,也就是说我要停服维护30个小时,这是不能容忍的。他们就想怎么优化,然后发现底层的存储过程写的有问题,表设计的也有问题,包括数据库存储的压缩方式全部都有问题。那这一套该怎么弄?重写的话估计两个礼拜都搞不定,所以这个时候怎么办?当时是2011年吧,我们就把服务器换成固态硬盘了,让玩家先没有任何问题的跑业务,然后拿过时间来再把它优化,这可能是一种解决问题的方式。有些同学会说,这不是偏产品吗?技术还是为产品服务的,技术是推动产品服务的。
下面我们会讲一些优化手段,这个手段可能应该是通用的。
逻辑帧其实是游戏里很重要的一个数据,玩家的交互我们必须要控制在150ms以内,这个时候怎么控制或者怎么分析出来?这些常用的地方,比如说因为我们有大量的对象就要分批计算、设置激活,刚才设置激活给各位讲过一次,就是说他看不到玩家的对象是不跑逻辑的。还有一个分批计算是什么意思?就是说我不可能一个逻辑帧把所有的对象跑完,所以就会分段来计算,这可能也能用到咱们某些地方,我确实对于互联网不是特别的熟悉。
在游戏里面它的同步其实是个非常要命的地方。大家都想玩,就是PK,晚上的时候我们有一个时间段是10点11点,那个时候玩家已经开始往下走了,理论上我们感觉就可以回家休息了,突然有一天运维打电话说网卡报警了,就是有A帮派和B帮派,两个帮派的老大冲突了,100V100在我们一个叫做桃花谷的地方,在我们没有优化之前每一个玩家动一下我要把消息发给周围的一百个人,那一百个人同时在动我就要发一万,一个逻辑帧就要发一万,我每秒有三十个逻辑帧,就是一秒有三十万个数据包往外发。后来这个地方我们怎么优化呢?就是在一个逻辑帧里面我就把一百个消息包合成一个发给我,那我的数据量就下来了,这个地方我不知道说的合适不合适,比如某个网站上请求一个网页,是不是可以把所有的地方压缩成一个东西发下来。
接下来是锁操作,锁操作我这边用的力度确实比较小一些,因为锁的力度大了以后很多资源要等待,这个都是常识。死锁现在已经很少发生了,因为锁规划合理以后其实没有大家想象的那么恐怖。我们有一个消息链条,我们在韩国的数据大概是一秒12万个数据往外发,分成逻辑帧,一个逻辑帧里面可能有几千个,几千个不可能锁住之后把它发出去,然后一个交换队列发出,就是尽量减少操作中的一些时间。
还有一个就是数据结构,这个就比较大了,就是说要把里面的成员变量压缩的尽量小,因为游戏玩家上线的时候要求效率非常高,3-5秒之内就要进入场景里面去,所以说它的存档要尽量小。原来在没有压缩的时候一个存档大概在3兆左右,后来优化完了之后剩下500K,也能算出来1秒能有多少存档。说到这儿咱们可以多说一点,好多时候在设计的时候就能算出来这个极限值,比如有500K,每秒能存二三十个存档就够了,因为好多是百兆的,所以这个时候在数据结构上的优化会特别多。
网络包的优化,这个可能大家用的也不多,比如刚才说了逻辑帧合并减少投递次数。大量的网络IO重点优化包,这个是什么意思呢?我们有一个log系统,log系统会记录每一个消息IP的包发了多少次,高峰多少次,平时多少次,每天把log看了之后,就知道哪个包异常了。所以在压力产生的时候,我写了一个控制范围,控制范围是什么概念?我走了一步因为椅子挡住了,所以只有前面的兄弟看到我走了,所以这就是一个控制的范围,这个包的数量就是一个级数级的减少,这个确实可能有点跨行业。还有一个是使用内存池,这个好像很正常,因为网络消息太频繁了,每秒大概十几万包往外发的时候,一天下来就几十个亿,所以必须要用内存池。
网络链接优化在游戏方面主要就是因为有网络攻击还有积分墙等,当时我们有一个网络攻击是山东的一个孩子,他连上断开连上断开,当时网络底层是Net 1.5的时候,它断开的处理没有完全释放,是半连接的状态,如果是完全释放就简单了。所以好多网络攻击,就是受到攻击的时候基本上都是自己的逻辑不够缜密。
撞库也是要命的,因为游戏最好获利,撞库之后帐号里有金币什么的就直接卖掉了,现在因为好多库已经被地下卖,每个系统上线的时候尤其是涉及到利益的时候,他撞你的库绝对是为了利益。因为MMO是有分析过,每秒的登录数是你注册人数的8%,就是非常稳定的值,比如说数据库里面有一千万个注册用户,每秒登录几千个人很正常,但是突然开始狂飙,数据库开始报警,数据库接口服务器也开始报警,这时候就发现好多人在撞库,现在就只能错IP了,然后就是加验证码。
这是线程的优化,有几个地方会用多线程:一是网络,一次交换收到的消息到处理线程;二是数据库,游戏里面写比读要频繁,所以分成读写锁,而且不能在关键节点存档;三是内部log系统,一次交换到写线程批次写入;四是游戏场景,不同的游戏有不同的操作,有的是多进程有的是多线程,不频繁操作,注意锁定时间。这里面有一个小的技巧,就是线程数要控制,因为我们做压力测试是有机器人的,机器人开太多之后机器人每跑一个,它的效率主要消耗在CPU轮片了,要保存在当前场景然后再切换调度,时间都消耗在那里了,所以线程数目控制在你认为合理的范围内就可以了。
存档数据库优化,因为这个库就相当于咱们银行里的存款,所以这个点的优化大概有几个点:一是缓存存档,我们专门做了一个缓存服务器出来,缓存存档还做了一个队列,队列里面会对存档次数包括它的一些算法保证优先级高的放在存档队列的最前端,让它优先存档,比如定时存档、升级存档是有一些优先级的;二是关键点存档,就是某些动钱的地方,关键的道具升级存档;三是压缩数据,因人而异,因为压缩和解压缩是有效率损失的。存档优化的一个目的就是保证不回档,好多时候有些外部因素是不可避免的,当时我们有一个在上海的机房,农民盖房子,一爪下去我们的服务器就疯狂报警了;还有按战区分档数据库,类似于分布式存储,存不了就只能分库,这里主要讲的是思想。

关于内存优化我不重点讲了,内存分配使用我们这边就是每一次内存分配都会记录下来,哪个地方每天分配了多少次,消耗了多少内存,是不是有内存泄漏,对于申请特别频繁的地方就会使用内存池。

我接下来讲一下log系统的优化,因为强调log系统是分析问题的基础,并且这么多年我一直对下面的兄弟对于log的系统是很严格的。比如我们的log有几种,一种是写在mysql数据库里的,直接通过我们的运营分析系统走策略服务器分析出来,一种是写到本地让运维系统去拿,不管哪种,都要在出问题时,第一时间定位出来为什么出问题了;大量log写入,分批次持续写入;log系统分级,控制写入阀值。比如玩家捡到100就不计log1万才记;统计系统同步,时间点选择,好多东西其实和研发团队没有关系,它是运维部署上的一些问题,有的运维会在晚上几点钟的时候把数据同步走,比如说备份或者进行其它的操作,如果要和产品进行沟通,会有活动或者再进行操作,或者是一些比较费的事情造成卡,当时运维在3点会有一个log的提取进行备份,然后程序那边认为凌晨3点没有人,会跑自己的一些东西,所以这个其实是一些沟通的问题,和优化没有关系。

调用第三方API优化,不要因为第三方影响你的系统。当时我们和马来西亚合作,他的API不稳定,一方面他的网络不太好,另一方面就是他动的时候不告诉你,但是我们的监控会自个儿监控出来。比如,我调这个API出来的时候预计有700到1000毫秒一个值就回来了,结果突然就暴到5000秒,结果发现是他们在调API的接口,所以对他们的接口还是要有一些log的记录。所以说尽量以一种不信任他们的态度去做咱们的系统,比方说第三方的一些超时、失败都要统计出来。
和业务上配合的优化,咱们的开发或者说咱们的架构是和业务相互促进的,好多时候其实它就到了一个极限值了,每一个计算机绝对有一个极限值,要突破这个极限值,好多时候就是一个业务上的调整了。比如游戏里面有一个叫做虚假繁荣点的设定,就是做假的,让玩家觉得人多,这属于一个不算是投机取巧,只能说是一个核心业务上配合的优化,不可能说计算机系统就一直把它优化到最牛,当然这不是跟产品的兄弟扯皮,能做的咱们尽量做,当达到一个极限的时候,或者有更好解决方案的时候,和业务上的优化是可以想一想的。活动修改,错峰进行,在游戏中有很多活动,包括网站上也有很多活动,比如打折、优惠券,比如我抢个7,抢7的时候如果这个活动跟你同时进行,再发个2000块钱的优惠券,这个时候网站就把数据飙起来了,当然这你可能错一下,从业务上就把这个东西解决了。
这里是与其它互联网产品一些互通性的思考,我特意加的一个东西,因为我是做游戏的,虽然做了十多年游戏,但是隔行如隔山,我始终认为性能大会上可能做互联网和移动互联网的比较多。我觉得高性能的设计是一种意识,而不单单是功能上的实现,就是说做的时候就想到了,我会算出来能承载多少人,IO是多少,CPU是多少,内存使用是多少,而不是说出了问题之后再优化。架构上设计的高效和可扩展性是基础,如果开始的时候没有想到扩展,上线的时候产品变化非常快,如果扩展性不强,加班熬夜就是咱们的常态。
所以,我想了一个东西叫做利用流程规避现在的风险。我这边做了一些流程,比如说设计文档,在每一个系统做的时候,任何一个小的系统我都会让下面的人写设计文档,设计文档其实是让大家输入自己的思路,我这边有一个模板,把这些模板做了,设计的承载、内存、网络、IO、数据操作频率都会考虑,我想用流程保证一个新入职的程序员写了这个东西他会考虑系统上线之后的效果。举个例子,当时我们有一个程序员其实还算比较可以的,写帮会系统,当时帮会系统是没有任何问题的,开始运行的时候也没有问题,但运行了一个多月的时候出问题了,玩家上线的时候点开帮派NPC瞬间掉线。当时那个帮会的数据容量大到一个程度,就是点击的时候瞬间会发送2-3M的数据包,socket底层缓存瞬间增满,然后网络层就把他踢掉了,这个时候他没有想这块承载需要多少个帮会,比如设计一千个帮会或者一万个帮会,一个帮会占多少内存?那这个帮会要往下刷新的时候会有多少的网络包往下发,这个时候如果把文档写完了就会规避这个问题,所以我说用流程规避风险。
然后是过程监督,虽然设计文档已经足够细化,你把模板做得足够的细,你要关心的那些点,比如说调数据库请求有一个事务操作,你就告诉他每秒请求多少次,你在什么时候的极限值是多少,超过这个极限值你是不是写log,你把这个都给规划出来之后,这个系统就不会把整个系统拖死掉,这是一个思想上的东西,我觉得这个思想可能各个行业都可以用到,不光是游戏里面。
然后就是定期利用一些分析工具去诊断效率问题。我们有一个管理配置小组,它有两个职责,一是规范、优化流程,开发和发布都会定期发布一些新的工具或者想办法优化一下,这个时候就会定期利用诊断工具诊断这个效率,我们现在是每两周跑一次,每发布版本跑一次。说到这可以再扩展一下,不光是效率的问题,我们还有一些静态的代码分析工具和动态代码分析工具都可以定期去跑。跑完之后最起码我们的内存泄露包括一些空指针,一些非法的引用都可以规避掉,所以我感觉这也是一种思想。
真实的外网测试环境,这个是什么意思?有的东西不到外网是看不出来的,好多差距就是网络差距。现在好多测试公司会在全国各地给你布网,去测你在某个节点的反馈是多少,我们2006年的时候写了一个网络引擎,在内网测没有任何问题,5000人在线,在内网来回大概心跳包的数值在30个毫秒。然后就上到外网去了,外网一压是600,怎么回事?分析半天最后发现在外网握手时要有一些确认值,因为网络差异会让包的确认时长非常长。不过现在中国的网络已经好多了,我们跟柬埔寨有合作,跟缅甸那边都有合作,柬埔寨维护的产品兄弟提前给我们发邮件说我们明天全国断网,所以中国的网络确实已经好很多了。
这个是log系统,我对log一直比较看重,因为log确实是分析问题的最后一个办法,因为它不像网站可以随时更新,可以调,服务器流程比较长,经过的部门也比较多,所以我们这边设置一些log等级。比如,实时记录log的等级,包括分模块、分功能的统一分析,比如说道具的获取、金钱的获取、升级。再一个是峰值、均值、执行次数等统计,我觉得log凡是能想到的都把它记下来,因为你会有用到的那一天。还有特殊性指定记录,某特定行为等。所以说系统的log是我特别看重的点,我不知道在座的是怎么想的,这是我的心得。
灵活可控的开关系统和配置文件。随时指定某个模块开放或关闭,因为游戏是实时运行的,比如三千个玩家在线是不能把游戏关掉然后上传新的版本启动的,这个时候对于一些不重要的系统,比如邮件或者聊天就关掉。当时有一个非常简单的小bug,就是序列化的问题,一个邯郸的玩家在全服聊天,他利用道具的bug,一点所有的客户端全部掉线,他就跟我们说我要炸服,他这话是周四说的,我们周六已经预定了两百万的广告要推广了,我们给玩家打电话问他怎么弄的,他说就是聊天,但是非常简单,我直接就在服务器上把聊天功能关掉了。
随时控制物品的产生,可能现在和咱们这个确实不太搭,随时控制物品的产生,什么意思?比如说咱们有一些抽奖,会控制一个物品产生的概率,因为原来比如说概率是十万分之一,结果少了一个零,变成了万分之一,所以说拿个开关把他控制一下把他关掉,这个东西就不许出。当你做产品做到高级别的时候,你会发现自己不光是技术,绝对和业务相关。
随时控制任务ID的完成和接取,他用任务的原因就是他有利益,任何玩家去操作系统的某一个漏洞的时候都是因为利益,不光是网站或者说移动互联网,原来咱们有刷任务,刷金币,就是把任务完成之后通过NCP转一圈再刷金币,这个时候怎么办?就把任务关掉,不能维护服务器,维护服务器成本太高。
虽然是跨行业,但是不知道大家有什么想了解的可以聊一聊,确实十多年,不论是做程序还是做技术还是做管理,有什么想问的都可以聊一下。
Q1:因为你一直在强调写log,大量写log对应用的性能其实会有一些影响,尤其游戏里面影响可能更大,在这个里面你们是怎么平衡的?
田博辉:是这样,写log的时候确实流量会比较大,我大概每天会有40G的log,第一我会把log分级,会写重要级的log,最严重级的log,严重级的log,警告级的log,会根据不同级别写下来。然后还有事务级的log和系统级log,事务级的log比如掉了一万块钱的金币,我可能只记两万的,这个一万的就不记。然后我们在每个道具身上会有一个道具估值,当道具估值低于阀值也不会记log,有一些任务log也会有一些估值,log系统我们也有开关,比如log量太大了我们可能把log关闭掉,现在我们这边log是单独有一台服务器来做的,现在的方式暂时没有出问题,因为log发的时候确实有一些性能损失,但是没有想的那么多。
Q2:其实我比较关心的不是性能,而是你说的逻辑,我比较关心逻辑这方面,比如你怎么通过日志去发现游戏的逻辑是封闭的,你有没有这个方面的一些感想?比如说我想攻击你,一定是你的逻辑上面有问题,你怎么通过日志或者说我有一些定期的逻辑来检查我可能会有些的问题。
田博辉:是这样的,因为在我们的集群里面有一个服务器叫做反外挂服务器,反外挂服务器里面确实有一些记录,比如刚才我说的一个例子,就是我们会有8%的登录机率,会算如果这个玩家在多长时间内登录多少次之后我就判断他有问题,就给他发验证码,这是一种机制。还有一个就是每个系统里面会有阀值,比如金币流动或者金钱流动,就像银行大额金钱流动会有通知,包括邮件、手机都会有通知,这就是一些阀值的设定,每一个系统里面有一个分析系统,比如道具里面有一个道具复制检测机制,就相当于它产生的那个数会有一个约定,当它超过约定值,范围过大的时候会把它记录下来,由产品再做分析,有的时候做不到特别智能,但是分析是可以做到的。因为一个人会影响一个服,假如说咱们京东上面有转的那种网站,假如他一转转到一千万个金豆那是不是要死人了?大概就是每个系统里面都有一个阀值的概念。
Q3:就是说还是有一个限制值。
田博辉:对,因为每个系统设计的时候是有一个值的,比如今天银行取款限定就是50万对不对,你要超过50万就不行了,就是这个意思。
编 辑:孔垂帅
余承东: 华为超越苹果三星 需四到五年时间
CCTIME推荐
CCTIME飞象网
CopyRight &
By CCTIME.COM
京ICP备号&& 京公网安备号
公司名称: 北京飞象互动文化传媒有限公司
未经书面许可,禁止转载、摘编、复制、镜像大型网络游戏中服务器的作用是?_百度知道
大型网络游戏中服务器的作用是?
我有更好的答案
上传下载数据,处理数据。存放数据文件。数据交互的作用!------------------------希望你的问题得到解决;*****望采纳*****------------------------
是不是只有交互数据?还是游戏的一部分在服务器上运行?
那是处理游戏数据的软件
专业电脑维护
处理数据各种数据
其他1条回答
为您推荐:
其他类似问题
您可能关注的内容
网络游戏的相关知识
换一换
回答问题,赢新手礼包
个人、企业类
违法有害信息,请在下方选择后提交
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。聊一聊游戏服务器架构设计-聊天功能的那些事
我的图书馆
聊一聊游戏服务器架构设计-聊天功能的那些事
& & 今天和小伙伴们聊一聊网络游戏架构的那些事,想必每个玩过联网游戏的小伙伴们都知道游戏内部会有一个聊天功能,那么我们来扒一扒这个看似简单的聊天功能。
一、世界喊话
& & 首先我们知道一般简单一点的聊天室的实现方式是你发一条消息广播给所有人,这样大家就好像都在一个屋子里互相都能看到对方的发言。很多大学、专科的学生都实践过这类功能。
& & 这种聊天室的工作模式可以用下面这张图来表示,一般我们实现这类功能只要服务器收到消息之后把消息分发到所有客户端上就可以了。服务器上只需要维护一张全局用户表就可以。
& & 有了聊天功能,现在游戏中的玩家终于可以开口说话了,只不过这个世界比较赤裸裸没有什么隐私可言而已。
& & 世界如果总是那么赤裸裸的,那要让游戏里的小情侣们怎么过日子呀。小情侣们之间羞羞的话题怎么好让所有人都看到呢。于是除了大家在一起互相聊天之外,还要有密聊的功能。
& & 密聊这个功能本身的特性就是聊天对象有着非常明确的目标,就是 A 到 B 两个玩家之间单向的消息传递。服务器在转发这类消息的时候就可以不用去循环便利所有玩家,只需要找到特定的玩家把消息丢过去就可以了。实现起来也不难。
三、小队频道
& & ok 这个系统目前可以让我们的游戏玩家可以互相自由的聊天了。但是我们知道玩家一旦多了,就会发生大家的聊天变成了刷屏。于是我们开始为不同目的的玩家划分频道,比方说玩家A 聚集了 5个小伙伴组成了一个小队一起去打 boss。于是聊天室里就多了一个概念叫做频道。大家聊天可以根据不同频道进行聊天。
& & 而频道于全局聊天的用户列表不同的是,在频道中只有有限的几个玩家。so,频道也是就是几个玩家的列表而已。给频道内的玩家发消息就变成了循环频道列表发消息,实现起来也不难。
& & 频道的出现可以非常方便的解决一小部分人的组团聊天需求,要想实现这类功能首先我们要在服务器上先要能动态的创建出消息容器,当两个人以上完成组队的时候,我们就可以用队伍的 ID 来充当 队伍频道的标示符。不同于广播的是,我们在整个游戏聊天服务器中相当于创建了多个小聊天室。剩下的就是只要队伍中的人在发队伍消息的时候,只需要带上频道 ID 为队伍 ID 就可以了。不同的队伍拥有不同的小聊天室,这样就可以完美解决频道聊天的问题:
& & 这个时候游戏的聊天系统稍微复杂了一点,已经有全局喊话、密聊、频道聊天。这么多种的聊天消息的来源都要接入,不同的频道还可能存在加入和退出的情况。这个时候我们需要为消息的传递设计一种工作方式,这样传递消息才能尽然有序。
& & 喊话的玩家把喊话的消息发送到 公共聊天 InBox,公共聊天 Inbox 接到消息之后再把这个消息转发所有玩家。队伍聊天时把消息发送到自己的队伍 InBox 里,然后队伍的 InBox 在把消息转发到队伍里的玩家。
五、本地聊天
& & ok,到了这里似乎整个世界都可以正常流转了,大家也不用满世界的刷屏喊话。可是玩过游戏的玩家都知道,一般我们在城里的时候通常可以看到很多玩家在相互聊天,一旦是当我们远离城市去做任务的时候就收不到那么多聊天信息了。
& & 如果周围只有你自己一个人的时候,通常聊天框里就只有战斗信息。但是我们自己心里都知道这并不代表别人在城里没有说话,而是已经收不到他们的聊天信息而已,这就是本地聊天的作用。
& & 还有一种本地聊天的 case, 离你附近不远的人说话你可以看到,但是他离你足够远的时候就收不到聊天消息了。本地聊天更像是人在现实环境中所能听到范围,离你太远的人说话是听不到的。
& & 让我们想一想,这种情况如果每个人都是如此会是怎样的一种场景(下面列出两个人的,如果更多呢?)
& & 在图中只要发送消息的人,每次在发送聊天消息的时候确定一个范围,并且把消息发送给这个范围内的其他玩家,就可以实现本地聊天。
& & 要实现本地聊天,其实就是筛选距离符合条件的,那么我只需要计算两个聊天人之间的距离就可以了。初中的知识,直角三角形计算公式这回终于排上用场了。
& & 假定我们接收消息的半径是 R,那么位于蓝点位置的玩家能否接收到红点位置玩家发出的消息就变成了。计算 红蓝之间距离是否大于 R 的算数问题。
六、3D下任意两个点之间的距离
& & 二维情况下我们可以画圆圈,3D情况下就要画球。下面我们开始画球,一个玩家一个球,两个玩家两个球,一堆玩家就是一堆球。画球是因为我们要考虑虽然两个玩家都站在一个平面坐标上,但是由于高度不同,彼此太远也会收不到对方的消息这种情况。 否则 3D 模式下画的就是圆柱了。
& & 在 3D 情况下计算任意两个点之间的距离计算会比较复杂,首先任意两个点之间可以看成盒子的两个对角线。求两点之间的距离就是求两个点所处平面的直线距离。为了得到这个平面我们需要先把这个盒子用刀切成一个三角形的奶酪。有了这个奶酪就可以计算红蓝的距离了。所以整个计算会涉及到两次直角三角形计算,大致示意图如下:
& & 现在开始动笔计算吧,在立体空间中我们如果忽略高度,那么红蓝这两个点就会形成在一个平面上。在这个平面上的点就成了一个虚拟的点(绿点)。而这个绿蓝两点的特点是除了高度之外其它坐标值相同,因此我们第一步先计算红绿之间的距离。如果红点为 {x1,y1,z1},蓝点为{x2,y2,z2}那么计算红绿的公式就是:
& & 接下来我们开始在奶酪斜面上计算斜边边长。还是直角三角形计算公式:
& & 下面我们把两个公式合并起来,顺便做一下简化。
& & 现在我们可以写一个函数来计算长度了。
七、别高兴的太早!
& & 到现在现在似乎所有问题都解决了,我们在回顾一下 InBox 现在的模样:把本地消息发送到专有的 InBox 里然后在转发的时候进行 Filter 计算距离做一下判断,现在应该是这个逻辑。
& & 看上去似乎完美了。现在假定:如果有 1000 个玩家同时在线,其中一个人说了一句话,那么这个人的这次发言就要把所有在线玩家的距离都计算一遍,这是1000次计算。那么如果这1000个人在世界里都说了一句话就要计算 1000 * 1000 一共 100W 次的计算。
& & 如果说话的人频繁说话呢? 200W次计算? 500W 次计算?还是 1000W次计算?, 倘若是 3000人在线呢? 或者万人在线呢?&
& & 话说我们可以控制一个人的说话频率,但是这个计算量是指数级的增长。单独控制一个变量是没有用的,所以我们还是要从发送消息的角度去控制。毕竟我们不能控制整个世界的聊天频率,这不科学。
八、用空间换时间!
& & 前面提到的方案里最大的问题就是计算量的问题,那么有没有一种方式可以避免大量计算呢?&
& & 我们先假定地图是二维平面的,所有人都在这个二维平面网络上。然后我们把大的地图网络划分成许多个方块,根据玩家坐标都可以归类到某一个格子里去,例如下面左边的图:
& & 接下来,我们为每个格子打上 ID 并为这个ID创建一个专属的地图频道。这样一来地图上的所有位置都对应的有一个唯一的地图区域聊天频道。
& & 现在只要把玩家发出的聊天消息发送到特定格子的频道里就OK了,其他玩家只管接收他所处的地图频道內聊天信息就可以了。
& & OK,现在剩下的问题就是如何把玩家放到格子里的事情。这样一来我们就不需要再去遍历全部玩家列表,也不需要去计算玩家距离,只需要往特定的频道里发消息就ok。
九、画格子
& & 首先我们知道游戏地图都有地图的坐标系统,在3D游戏里表示一个游戏内玩家坐标可以用 x,y,z 三个量来表示。而我们的聊天频道是根据二维平面来计算的,那么如果忽略玩家所处的高度。我们的3维坐标也就变成了我们需要的二维坐标。
& & 另外一个问题,如果我们为地图上每一个坐标都创建一个频道,那玩家和玩家之间只有亲密站在一个点的时候才能收到彼此的消息。这个也不是我们所看到的。因此我们需要把 100 *&100 的地图坐标映射到 3 * 3 的频道网格里。
& & 现在我们假定玩家位于蓝色地图区块内说话,他的地图坐标相当于 5,5 ,聊天频道区块的坐标相当于 2,2。
& & &我们需要一个函数,让用户坐标经过这个函数的时候变成 2,2。 这里可以把两个二维网络当作完全相同的两个地图,只是比例尺不太一样。那么我们只需要找出两张地图的比例关系。在把玩家的实际 坐标和比例关系相乘一下问题就结了。
& & 根据这个 case 我们知道,消息格子和地图之间:&x 轴的比例关系是 &3:9 = 1:3 , y 轴上比例关系也是 3:9 = 1:3 。
& & 这样就可以得到这样一个近似的转换坐标。 x: 0.33,y=0.33。接下来玩家的实际坐标 &5,5 乘以转换坐标 0.33,0.33 得到的就得到 x =1.65 , y= 1.65。
& & 然后再把这个结果做 “Math.ceil”的取整,最后得到了格子坐标 2,2。接下来就把消息发到这个格子的频道去就好了,其他在这个频道的玩家都会收到消息。哪怕有 100W 人在线,也不需要去计算任何距离。CPU 效率用到最大化。
9.1 - 3D下的格子
& & 3D下画格子看似很玄乎其实就是一个两个魔方套在一起,道理是一样的。计算方式也是一样的。甚至通过坐标转换两个格子的函数也是一样的。
& & 例如:消息格子和地图之间:&x 轴的比例关系是 &3:9 = 1:3 , y 轴上比例关系也是 3:9 = 1:3 , z 轴上比例关系也是 3:9 = 1:3 。
& & 这样就可以得到这样一个近似的转换坐标。 x: 0.33,y=0.33,z=0.33
& & 接下来玩家的实际坐标 &5,5,5&乘以转换坐标 0.33,0.33,0.33 得到的就得到 x =1.65 , y= 1.65,z=1.65。
& & 结果做 “Math.ceil”的取整,最后得到了格子坐标 2,2,2。 这个格子就是魔方的正中心,如果玩家 z 坐标小一点到 2,那么坐标计算之后 z 格子 就是 2 * 0.33 = 0.66 ,取&Math.ceil 计算后得 1,这样玩家就跑到盒子的上面去了。
9.2 - 真的就解决问题了么?
& & 好盒子画完了。现在让我们在微观上,重新审视一下本地聊天系统是否还存在其它问题。
& & 如下图所示,现在有三个玩家,根据他们实际的地图坐标已经把他们划分好具体的格子。我们发现:红蓝,两个玩家虽然距离上很接近但是处于不同的格子。这个会造成蓝色玩家把消息发送到左边的格子里,那么红色的玩家就不会在右边收到他的聊天消息。即便是他们两个如此近距离,这也不是我们希望看到的。
& & 再来看,蓝色和紫色玩家因为在一个频道内即使距离很远,紫色玩家依然可以收到,我们可以认为格子的斜边长就是紫色玩家听力的极限范围。这么去解释也说得通。但是绿色玩家和蓝色玩家之间的距离明显比蓝色和紫色的要近,收不到消息有点说不通了。
& & 好吧,为了解决这个问题我们还要解决发消息发往哪些格子,至少目前开看还要把消息发往周边的格子。为了方便理解让我们开始继续画格子把:
& & 这样一来,就解决了我们遇到的蓝色玩家发的消息,紫色玩家收不到的情况。 3D 情况下,大家可以自行脑补一下 3 * 3 * 3 的格子方阵,道理是一样的。
9.3 - 处理玩家移动
& & 玩家不是一直就站在原地的,玩家会动。这也就说明,我们给玩家圈定好的聊天频道会随着玩家的移动而发生变化。所以地图频道还要有进入频道、离开频道这样的基本功能。当玩家进入一些格子之后就必然要离开一些格子。
9.4 - 还可以更完美么?
& & 我们说做事情要有匠心精神,现在看样子我们已经完美的解决了本地聊天的问题。现在我们在重新审视一下我们的设计是否还有其它漏洞。
& & 我们知道声音是按直线传播的,在传播中会逐渐衰减。假定一个人正在讲话,从能听到他讲话到听不到他讲话的距离是20米,那么两个人听力完全相同的人,理论上无论他们在什么位置只要以讲话人为中心,20米的范围内都可以听到讲话。一旦超过这个距离就应该听不到。
& & 我们画一个模型来表示这个意思,同时对比一下我们的格子模型。为了说明问题,我把发送范围扩大到 7 * 7 的范围。
& & 大家看到了把,在真实环境中的人(绿点)在我们的格子模型中居然收到了消息!
& & 为了让系统完美一点我们继续画圆(如上面右图)首先我们知道消息的发送最大半径为 3 个单位,那么算上消息发送者自身的起点为圆心,整个半径应该是 4个单位,直径是 7个单位。接下来我们要找到这个圆圈所在的正方形四个顶点。
& & 假定消息发送的格子坐标点为 {x= 25,y =20} ,那么最大喊话半径为 3 ,可以得出一个矩形对角线坐标为 {x-3, y-3}{x+3,y+3}。接下来只需要循环这个矩形的每个点,都和中心点做一个距离的计算然后排除掉超过半径的格子就会得出我们最后希望收到消息的格子。
& & 如果大家觉得 7 * 7 的格子的圆太过粗糙,可以提升半径数以增加圆的光滑度。举个例子:喊话半径为 100 个单位,那么每次喊话的计算量在 w=201,h=201,4.04W。
& & 我们来直观的看一下 &50 半径的光滑度是个什么样子的,图中每个红色格子里面都是一个 10 * 10 个小格子组成。
& & 在看看 半径 100 单位的格子光滑度(为了方便,使用一张 201 * 201 像素的图片作为代表),怎么样够可以了吧。
& & 实际上需要这么细腻么?我们 50 半径就已经很给力了。
9.5 - 追求极致性能!
& & 到目前为止我们定义的格子模型和地图坐标系统之间是静态的关系。格子和格子之间的关系始终是静态的,玩家移进移出格子不影响格子与格子之间的关系。那么格子的关系既然是静态的,那么整个世界上如果都遵循这一个定律(消息最大传播半径 100),是不是就可以预先把每个格子都算一遍。这样玩家在发消息的时候就可以避免 4.04 万次的计算。然后把每个格子的计算结果都作为格子的一个属性预先保存在内存里。
& & 如果这个配置是整个服务器的基础配置,我们甚至可以把计算的结果保存到磁盘上。这样每次服务器启动加载格子数据的时候,都不需要做计算了。
& & 效率最大化,这正是我们希望看到的!
& & OK 现在我们看样子已经解决了所有问题,玩家发送消息的时候玩家在地图上任意位置发送消息给所在地图频道以及周边的频道。这样周边的玩家就可以收到聊天消息。现在在回头看看我们的 InBox 的模样,还是那么简洁。
十、格子画多少比较合适?
& & 画多少格子说白了就是在考虑系统承载力的上限多高,因此我们要尽量把数字合理的夸大一些。然后评估出系统能力的边界,这就好比淘宝每年做双十一系统压测,都是把数字夸大好几个量级。让它成为一个看似不可能达到的上限。
& & 下面我们就开始评估我们的系统设计上限,通过“假定-&&计算 -& 调整”。我们可以得到一个比较靠谱的数值,现在就让我们先从最不靠谱开始吧。
10.1 - 地图大小
& & 现在开始,我们来讨论一下画多少个格子比较合适这个问题。在讨论这个问题之前我们先看看全局地图到底该多大,在此之前我们用真实世界的 米 作为计量单位。
& & 先假定一个游戏有一张很大很大的地图,按照玩家每秒 1 米的移动速度。假定玩家从最东边跑到最西边需要 24 小时,那么游戏的地图应该有&86,400 米。
& & 如果这个数值换算成游戏地图面积应该是 7464.96 平方公里。
& & 游戏设计者在这么大的面积上,可以把一座巨大的山峰设计成 100 米,长江的宽度设计成 10 米。总之把你的地形数据适当的缩小,那么这个大地图可以表示你想要的一切。而且它的单位面积也足够大。
& & 在真实游戏环境地图坐标上我们可以采用 小数 来表达以扩大地图精度。7000多平方公里的地图资源,应该是足够用了。当然不够的话可以在加!
10.2 - 消息格子数目
& & 格子尺度越小,格子数越大,假如一平米一个格子,那么场地面积就是格子数。可以写作:n=(x /&a) * (&y / a) ;n&= xy / a ^2。
&&&&(n:最总格子数,x:x轴地图尺度,y:y轴地图尺度,a:格子划分尺度)
& & 我们假定 x=y,那么(n = xy / a ^2,变为:n= x ^2 / a ^2&),先看一下&1:1 关系下格子数的曲线。可以看到 x 轴我们的地图尺度不断增加,格子数的增长非常快。
函数曲线生成地址:http://www.archimy.com/ ,下面是脚本:
z = 0xgrid = 86400a= 1y = (x ^2) / a ^ 2
如果比例单位小一点呢?我们调整比例关系 a ,来重新对比格子数增长情况:
& & 为了确定我们的演算结果,我们按照上面的比例系数算一下&86400 米见方的地图上格子数是怎样的:
& & 1米单位: 个格子[86400 *&86400];& & 3米单位: & 个格子[(86400 / 3 &)&*&(86400 / 3 &)];& & 10米单位: && 个格子[(86400 / 10 )&*&(86400 / 10 )];& & 20米单位: && 个格子[(86400 / 20 )&*&(86400 / 20 )];& & 50米单位: & &&2985984 个格子[(86400 / 50 )&*&(86400 / 50 )];
10.3&- 格子占用内存空间
& & 现在我们计算一下,要想把这些数量级的数字记录到内存里究竟需要多大。
& & ,这个数已经进入 long 的范畴,我们需要用 8 个字节进行存放,要想存下这么多的 8个字节数据我们需要 55.61G 的空间去存储。显然这是非常非常不靠谱的,直接放弃。
& & ,还在 int 的范畴,可以用 4 个字节来存储。这个数我们也算一下,大约需要有 3.08GB&的数据存储空间。还是太大,也直接放弃。
& & ,这个数我们也算一下,大约有&284.76MB&的数据。这个数量还可以接受。
& & ,这个数我们也算一下,大约有&71.19MB&的数据。这个数量不错。
& & 2985984,这个数我们也算一下,大约有&11.39MB&的数据。这个数也很不错。
10.4&- 与周边格子关系数和存储
& & 那么已玩家为中心,玩家说一句话所影响到的格子数我们通过圆的面积来粗略计算。如果一公里地图长度,按照 10 米单位为切分的话,整个地图的宽度就会缩减到 100,100为直径的圆圈内粗略算一下面就可以得到格子数。废话少说上公式:
n:为我们要求出的某个格子周边关系的近似数。a:实际单位:米b:划分格子的度量,即多少米为一个格子。
& & 公式有了,我们现在假定玩家具有河东狮吼的能力,每次说话会让周边 3 公里的人都听到,同时我们使用 10米 这个单位。那么带入公式得到:
n= 3.1415 * (3000 / 10)^ 2 ,约等于&282735,就是说在 10米 为一个格子的情况下,玩家说一句话让周边三公里内人都听到。需要当前玩家所处的格子与周边约 28.2W 的格子进行关联。同时如果每个格子都要这样做关联那么将会产生巨大的关联关系(相当于 * 28.2W),这个数值必须被否掉。
& & 还是两条路,1.降低格子数;2.降低消息范围。
& & 在这个case中,消息传播距离 3 公里实在是有点太夸张,那么我们降低到 1 公里,或者在降低到 500米?下面直接上结果:
1公里:31415 个关联格子,约3W;500米:7853.75个关联格子,7800多个;
& & 这个数值很不错!如果每个格子都预先把周边 1 公里的格子做好关联,那么就会是: *&31415。为了降低存储空间,31415 使用 两个字节的 short 表示。这些关系一共需要& *&31415 *2 个字节,约为:4368.12GB 这绝对不可能让它发生。
& & 好吧,试一下 500&范围的: *&7853.75 *2,约为:1092.03GB,这也太高了。看样子降低范围已经不能解决问题了,我们需要降低格子密度!
& & 使用 20米密度再算一遍关联格子数(格子数):
3公里 (n= 3.1415 * (3000 / 20)^ 2 ) &&70683.75 个关联格子,约7W;1公里 (n= 3.1415 * (1000 / 20)^ 2 ) & & &7853.75 个关联格子;500米(n= 3.1415 * (500 / 20)^ 2 ) & & & 1963.43 个关联格子;
& & 我们在重新计算一下所有关系需要的存储空间:
3公里 ( *&70683.75 * 4)约:4914GB,无法直视。直接放弃(乘 4 是因为 70683 这个数需要 4个字节来存储);1公里 ( *&7853.75 * 2)约:273GB;500米( *&1963.43 * 2)约:68.2G;
& & 看样子 20 米单位的格子密度还是太高,现在只有选择 50 米密度了(2985984)。再算一遍,这次直接给出结果:
关联格子数:&&&&3公里(n= 3.1415 * (3000 / 50)^ 2 ) &&11,309.4 个关联格子,约1.1W;&&&&1公里(n= 3.1415 * (1000 / 50)^ 2 ) & & 1,256.6 个关联格子;&&&&500米(n= 3.1415 * (500 / 50)^ 2 ) & & & 314.15 个关联格子;
存储大小:&&&&3公里 (2985984 * 11,309.4 * 2)约:62.9GB;&&&&1公里 (2985984 * 1,256.6 * 2)约:6.98GB;&&&&500米(2985984 * 314.15 * 2)约:1.74GB;
10.5&- 不建议划分3D格子
& & 前面我们讨论的数据都是 2D 地图上的格子数据,假如你觉得。在30层楼的人不应该听到 1 楼人的窃窃私语,那么解决办法有两个。
& & 1. 缩小消息传播尺度,同时或者增大格子单位。&& &2. 不使用3D的格子模型,在格子转发消息的时候。对接受消息方的 z&轴做数值判断。因为计算量小可以“时间换空间”。
& & 先说第一种方法,为了找出计算机可以接受的格子数。将格子单位从 20米 提升到 100米,我们的地图模型假定是一个立方体。因此格子数等于:(86400 / 100 )& ^ 3 =644,972,544, 6.44 亿个格子。6亿个格子 ID 用 4字节 int 来存需要用到约&2.4GB 空间。
& & 同时我们降低消息传播范围到 100米,利用球体积公式(4/3 * 圆周率 *&半径的立方)得到每个格子周边可能有关系的格子数近似值约:4.18。
& & 注意:这里因为我们传播半径为100米,格子半径也是100米。按照常理来说这样的传播范围应该是一个 3 * 3 * 3的方格,因为距离实在太近了,以至于我们无法用常理的球体积公式来进行计算。
& & 可就是即便采用球体积公式的结果 4.18 我们也发现,6.44&亿个格子每个格子都有约 4.18 个临近对象的话。光是存储空间就需要&2.4 * 4.18 GB 约 10GB 的空间,再加上个格子ID的存储空间,大概需要 12G 的空间!!!
& & 因此我更建议使用第二种方法实现立体范围的消息传递,因为在游戏中同一个格子上垂直方向上不通高度密集分布玩家的情况不太可能发生。而画立体格子的代价实在是太高昂了。
10.6&- 回顾我们选择的参数
& & 看样子,我们找到一个适合的参数了。我们要在方圆&7,464.96 平方公里的土地上,画出大约 298.6W&个消息格子,平均每个格子需要记住周边&314.15 个临近的格子ID。这样的配置下,我们需要最小 1.74G 左右的内存,其中地图格子数据 11.39MB。
& & 这个配置看上去还可以,就先用这套配置吧。当然如果你想,可以自行调节(地图尺寸、格子比例、传播半径)这三个参数。调参数的手法前面已经演示的非常清楚了。
十一、看看具体性能如何?
& & 玩家在登陆游戏服务器之后。第一步,服务器根据他的游戏坐标,找到他的消息盒子。这个操作只需要用玩家的坐标乘以比例尺(0.2)在做一个 “Math.ceil”即可得到格子坐标。(产生 1 次计算)
& & 每个玩家都有一组状态数据,玩家初次登陆的时候根据坐标,可以预先算出,玩家像四个方向移动多少米之后会触发格子更新事件。接下来玩家每次移动都只要把移动消息发出来,交给这部分逻辑处理器去处理就好了。逻辑处理器负责计算是否要触发重新注册格子。(每次移动都会产生 1 次计算)
& & 进出格子的计算量,每个格子都有大约 314.15 个临近链接。每次一旦决定游戏玩家从一个格子跨遇到另外一个格子之后,需要比对两个格子之间差异的,最少需要做&314.15 *&314.15&次计算和判断,共计约&98690&次计算。好在这个计算量并不是每次玩家移动都会触发,不然这个计算量也不容忽视的一个问题。
& & 触发玩家更新消息格子的条件是,当游戏玩家离开所处消息格子时。这样一来玩家只要在我们单位尺度内,随意移动都不会造成玩家移动触发 9W 次的判断计算。例如下图:
& & 现在列举两个极端问题,看看系统会发生什么。假定单个大区服务器设定上线玩家数为:10W人。
& & 1. 当所有玩家都聚集到一个格子里,并每个人都说一句话。那么会发生什么问题?
& & 首先 10W 人都在一个格子里,意味着一个人说话会被 10W 个人同时听到。消息的转发次数是 10W 次,每个人都说一句话,消息的转发次数是 10W &* 10W。
& & 说实话,这种极端情况下我们也没什么可以做的。因为消息毕竟还是要发到每个人手里,我们能做的是尽量控制玩家过于密集的在一个区域内。况且 10W 个人物对象同时渲染在一个屏幕里,恐怕显卡也造就烧爆了。所以理论上不太可能发生。
& & 说到这个 case 我到想起早期 魔兽世界 屠城的时候,20个 40人团队,直接冲进联盟暴风城的场面。别说屠城了,去的人没有一个人能在当天出来,整个暴风城及其附近的几张地图全部遭遇服务器宕机。
& & 2. 所有玩家平均分布在两个格子之间的临界点,然后开始匀速的左右移动。这回造成服务器为每个玩家频繁计算 9W 次的进出格子判断。
& & 这也是一个不容小视的问题,解决这个问题也有很多办法。为了简单可用,我们设计一个专门用于保存玩家状态的服务器集群,20台 机器每台机器管理 5000&个在线用户,9W&次的计算会按照用户为维度,分不到不通的server上。问题解决合理解决。
& & 在下一篇博文我将会基于格子系统,介绍如何进行系统架构的设计。以及格子系统的另类关键用途,欢迎大家关注。
& & 以上内容欢迎大家参与讨论,说说你的想法,以及你的看法。
原文首发:
喜欢该文的人也喜欢

我要回帖

更多关于 维修服务器 的文章

 

随机推荐