编者按在8月29日的GWB游戏品鉴会上,腾讯天美工作室《使命召唤手游》服务器主程Jerry,分享了服务器架构如何优化以及常见的服务器问题解决方案,以下为文字版本。
分享/Jerry 整理/迪亚菠萝包
炸服,是近两年频繁发生、游戏厂商闻之色变的运营事故。
虽然从某种意义上来说,炸服意味着游戏很受欢迎,但由于炸服会致使玩家无法登录、频繁卡顿、反复重连,甚至出现数据丢失和回档,导致游戏口碑暴跌。一旦处理不好,可能会使一个原本的爆款丧失第一波爆发的机会。
从服务器架构设计的角度,如何避免上线即「炸服」的事故发生?
上周六,在腾讯游戏学院主办的GWB腾讯游戏品鉴会上,天美J3工作室《使命召唤手游》服务器主程Jerry分享了他对于服务器架构设计的心得。
其分享的要点如下:
看完这篇技术干货,说不定能帮助你的产品避开炸服雷区。
《使命召唤手游》服务器主程序Jerry
以下为分享内容,有调整和删节。
大家好,我是Jerry,来自天美J3工作室,现在担任《使命召唤手游》服务器主程。很高兴有机会和大家聊一聊有关服务器架构设计的话题。
今天这个话题,想必大家都会有所关注:游戏上线后出现炸服,可能是因为哪些原因?在游戏设计之初,我们需要注意哪些问题,才能避免或减少炸服发生?
那什么是炸服?我相信大家都听说或经历过这样的情况,游戏刚开服的时候,由于玩家特别热情,可能出现登录不上、频繁卡顿,甚至反复重连的情况,严重时可能会出现数据丢失、回档,而且这些问题往往不能快速得到解决。
从服务器设计的角度看,这些问题一般和下面这些因素有关:服务器架构设计不到位、平行扩容和负载均衡有缺陷、单点容灾考虑得不是特别完善。
我们先从一个案例讲起。这是某款游戏的服务器架构图,我们做了适当的简化。
这款游戏采用了分区分服的部署方式,架构图左边其实是一个区,主要包含登录授权服务,以及连接管理和游戏逻辑。同时,它有一个所有分区公用的对局管理模块,而它的游戏逻辑放在了战斗逻辑进程中,也是各个分区共同使用。
在功能层面,这款游戏的连接管理主要负责玩家的连接登录,游戏逻辑里包含了数据管理,角色养成等业务逻辑,而对局管理包含组队、匹配、开局逻辑等等,战斗逻辑主要负责局内战斗。
这款游戏在部署上有一个很有意思的点,开发团队认为这款游戏单区承载能力足够,因此打算一个大区用一台高性能物理机、主游戏逻辑用一个进程就搞定了。
这样的架构设计存在什么问题?首先业务耦合度特别高。他们在架构图里虽然把连接管理和游戏逻辑分开了,但实际上这两块在同一个进程中。连接管理和游戏逻辑放在一起可能会导致什么问题?
对于这款游戏来说,游戏逻辑里包含了很多游戏,所以业务逻辑会特别重,出现Bug的概率特别高,如果在线上运营,游戏逻辑可能需要频繁更新,如果将其和连接管理放在一起,会导致更新出现各种掣肘,一旦处理不当,就有可能导致玩家掉线。
其次,他们的对局管理模块包含了很多功能,比如匹配、开局、负载管理等等,由于全局只有一个对局逻辑,所以可能会存在单点容灾的问题。而对局管理和游戏逻辑放在一起,平行扩容方面也会存在问题。同时,由于他们把负载管理和匹配之类的功能放在同一个进程里面,在负载管理上可能也存在一些缺陷。
拓展一点说,在分区分服部署模式中经常会碰到另外一个问题:由于开发者认为游戏是分区分服的,每个区的玩家数量相对会比较少,所以他们只部署一个进程来搞定,从单区的角度来看形成了事实上的单点。
而这款游戏全服共享的「对局管理」只有一个进程,我们认为如果单进程能支撑所有的请求,那么至少应该设计成主备部署的架构。但在游戏上线前,你拿不准用户量会达到什么样的程度。万一你的游戏成了爆款,这种单纯的主备方式有可能满足不了实际的需求。因此,我们推荐将其设计成可以平行扩容的方案。
说到平行扩容,刚才那种事实单点是无法支持平行扩容的。对于这个项目,他们负责服务器设计的同学说,单区承载目标是5K-6K,但随着开发推进,游戏业务逻辑越来越复杂,通过压力测试发现,在这种逻辑架构下,游戏逻辑进程承载的极限只有3K。由于这种架构不支持平行扩容,游戏上线时很有可能发生炸服。
这款游戏的对局管理为什么不支持平行扩容?因为对局管理进程中包含的功能太多了,这些功能在同样的业务逻辑下,对性能的要求可能不一样。如果想要对其中某个功能进行扩容,在这种把所有功能都集成在一起的设计中显然做不到。
除此之外,这款游戏还存在负载均衡的问题,这个和架构设计可能没有太大关系,我们发现,这款游戏的对局管理存在算法缺陷。因为他们没有考虑到一台机器的瞬间负载能力,在新加入「战斗模块」机器时,可能发生雪崩。
因此我们设计负载均衡调度算法时,除了定时上报负载外,一定要设计异常上报机制,负载均衡算法必须能及时处理异常情况,并且实例——对于这款游戏就是战斗模块——必须要有主动熔断机制,避免出现负载本身已经承受不住时,负载调度模块还不断发送开局请求,当然这需要负载调度模块和实例之间互相配合。
同时,我们还需要设计提前预判机制。举个例子,目前我只剩下10%的负载,下一次上报时间可能在3秒以后,如果这3秒内调度模块发送了过多请求,很有可能会导致雪崩。
总体看下来,如果这款游戏以这样的服务器架构上线,万一玩家特别热情,刚才提到的任何一个问题爆发,都有可能引发「炸服」。
在这个案例中,我们指出了很多问题,也相应提供了解决方案,但项目组反馈说,可能没有办法做这样的修改,因为他们在设计之初就把服务器架构限死了,并且服务器底层架构缺乏相关的支持。
那我们在架构设计之初,能不能做一些预见性的设计,规避这样的问题?