前言

少三2成功 OB 已经一年多了,19年12月份,我们还在为项目 OB 艰苦奋斗呢。转眼间就过去一年多了,虽然在公司内部也做过一些 OB 期的技术问题总结,但都比较泛。今天有时间,想着还是从更细的角度深入总结一下,OB 时面临的技术难点在哪里?好好思考一下,我们下一个项目 OB 的时候,是否可以更稳更安全地完成 OB 任务。虽然我们经历过少三1的 OB,但在少三2的 OB 过程中还是有些不适应,也曾有部分技术细节没做好,导致部分的流量没抓住。我们主策同学曾经戏言,后端技术 OB 期给项目损失了200万广告费。我认为问题确实存在,所幸我们及时补救回来了,没有像某些游戏一样,上线即崩。为什么已经有了一些 OB 经验,还是不能很好地应对呢?主要原因是时代在变,技术也在变,历史经验只能作为参考,并不能完全照搬照套。要做好足够的预案,在 OB 时也要迅速反应,及时对当前的状况做出正确的应对。

何为 OB

OB 意为 Opened Beta,就是公开测试版本。在软件行业中,这只是测试版本中一个比较重要的节点而已,后面还会有 Gamma、RC、RTM 等等版本,之后才会正式发布 Release 版本。但在游戏行业中,因为 OB 版本开始需要保留玩家数据,不能进行删档操作了,因此 OB 版本就非常重要了。从运营侧来说,OB 版本存在媒体曝光的机会,曝光即意味着免费导量,OB 版本就显得尤为重要了,OB 版本能够做到的高度基本决定了游戏的命运,是功成名就还是功败垂成就在此关键一役。

何为分区分服类游戏

分区是从运营层面的区分方式,主要是游戏生态的考量,同区玩家存在直接的竞争关系,能够在游戏内互通数据,例如同台竞技、互为好友或者组成联盟之类的玩法。现在手游基本会把 AppStore 独立分区,因为该渠道的玩家付费生态较好。腾讯也是一个特殊的渠道,应用宝基本也会独立分区。然后就是安卓混服会放在一个混合分区,但目前也有很多其他特殊渠道会独立分区,具体要看运营如何分配渠道资源了。

分服是相对于通服的做法,大部分游戏都是分服的设计方案,因为这样服务器的承载就相对可控,分服之后单服的压力总归有限,技术难度相对较小。而通服的做法在技术上就显得高大尚一些了,必须采用分布式架构,无论是游戏内部的通信,还是玩家数据的存储,都会面临很大的技术挑战。

分区分服就是在分区的基础上,区内再按照生态以不同节奏开新服,通过区内跨服的玩法,将这些玩家的生态进行串联,能够提供社区类玩法,提高区内玩家的活跃度。分区分服类游戏的开服节奏相对较快,单服的玩家数有限,一旦在开服竞技中处于弱势的玩家就会选择换新服重头开始,也就形成了滚服玩家较多,老服玩家流失率高的特色。

OB 时的技术挑战

OB 就意味着曝光,有媒体也有渠道,游戏的知名度越高,OB 带来的流量就越高。以少三2 AppStore 渠道为例,首日就开出了22台服务器,每台服务器平均注册1万人,首日注册玩家数约为22万人。注册量大倒不是最大的挑战,最大的挑战却是在 OB 开启的那一刻的瞬间流量。这个流量是不可控的,峰值多少也无法预估,即使有历史经验也很难做参考。就拿少三2为例,仅 AppStore 这个渠道的量就已经超出了我们的想象,因为我们还拿着少三1 OB 的经验做预案参考,显然已经过时了。

按照之前的经验,我们为了缓解压力,会把 S1 服提前2分钟对外,我们对外公布 10:00 开服,S1 服实际是 9:58 开服的。从创角数据上看,开服前2分钟的创角量就直接超过了8000+,而开服后3分钟内的每分钟创角量也都在 8000+,明显 S1 服已经被爆服了。这个爆服并不是服务器真被撑挂了,而是因为服务器设计了防爆机制,单服同时在线超过阈值(6000)时,后续玩家登录的玩家就无法进入游戏了,这也难怪主策同学会说后端技术应该承担200万的经济损失。从 S1 服的同时在线数据来看,9:59 至 10:04 的这5分钟内,同时在线瞬间从4371攀升到 6000,一直持续到 10:29 都持续保持在6000这个峰值。从开服前5分钟内的创角数据看,9:58 至 9:59 这两分钟内,创角总量就已经接近1万,再加上 10:00 瞬间涌入的玩家,S1 服被爆服的事实是客观存在的。 从 10:00 开始 S2 ~ S8 等7台服务器才开始接活,之后半小时内涌入 S1 而无法正常登入的玩家就已经损失了,当然也有可能会因为进不了 S1 而选择去其他服务器试试,但更多的小白玩家会因此而流失掉了。

少三2 ob 数据

如何应对 OB

既然 OB 时导入的量无法控制,是否就只能承受这个损失呢?当然不是,以我两次 OB 的经验来看,只要做好足够的预案,完全吃下这些量是绝对可以的。少三2因为 AppStore 和安卓混服是分两期 OB 的,我们在 AppStore 吃到的亏,在安卓混服 OB 时就很好地避免了。结合我们已经做到的,以及我们还没做到的,我觉得都有必要总结一下。

1. 系统稳定可靠

打铁还需自身硬,不管导入的量有多少,自身系统必须稳定可靠,否则就是竹篮打水一场空。如果你是系统架构设计者,是一个没有被验证过的架构,那就把这个架构简单化,不要贪图高大上的复杂架构,因为你可能 hold 不住。如果是一个已经被验证过的架构,那也不能掉以轻心,你得对这个架构的优缺点做到心中有数,在业务设计时,必须扬长避短,不要一味地跟着策划天马行空。如果有些策划想法因为技术架构的性能瓶颈做不到,并不丢人,如果强逞去做,最后影响到整个系统的性能就得不偿失了。所以,在能够满足业务需求的情况下,确保能够提供一个高性能的服务,是一个技术人最基本的追求。

2. 提高承载数据

在确保系统拥有足够高性能的前提下,努力提高系统的承载能力是一件极有挑战性的任务,这就是游戏系统的高并发要求。游戏系统的高并发和网站系统不是一个概念,游戏系统的高并发通常是指系统的同时在线人数,游戏系统架构越复杂,可承载的同时在线人数越高,但面临的技术挑战也越高。除了最高同时在线人数之外,还有最高创角人数,这个和游戏框架的数据库设计有关,数据库的选型与部署方案决定了单服的最高创角人数上限。

当系统架构已经完成,开始业务铺量开发了,这个时候需要按照版本节点,对版本中的业务进行压力测试。从这些业务的系统运行情况与数据承载情况,发现系统架构的瓶颈所在,然后对瓶颈问题进行分析与改进。这个时候可能会面临系统架构的技术性调整,要做好改动的可行性评估,这种改动手术就真正考验到架构设计者了。然后,你得在一个循环中不断优化,通过压测发现问题,找出技术瓶颈,分析原因并解决它。最终将系统的承载数据提高到一个可接受的范围,这个数据必须得到运营方的认可,然后在 OB 期导量的时候大家都要心中有数。

3. 让系统高可用

高可用是所有软件系统通用的对于服务时间的衡量标准,理论上需要的是 100% 提供服务的系统,但实际上很难做到,很多大公司对系统的高可用标准是 99.99%。游戏系统和传统软件系统对高可用的标准有一些差异,主要体现在,游戏系统允许短时间的停服更新维护,而传统软件系统是要求7*24小时的永不停服的服务。并不是游戏系统不想要永不停服的服务,而是系统本身的复杂性,以及技术的实现难度,很难保障在不停服进行系统更新的同时,还能提供不间断的服务。当然,有一些技术手段是可以实现不停服更新,但也存在一定局限性,比如只能更新部分代码或配置文件。

抛开停服更新这个唯一允许停服的时间之外,游戏系统对高可用标准和传统软件系统是一致的,任何因其他原因造成的服务中断,都是 S 级事故。因此,提供可靠服务也是游戏后端系统的一个基本要求,游戏系统不能因为业务开发的设计不严谨,造成服务的中断。这对于 C++ 技术栈的游戏系统来说,确实是一个挑战,主程必须时刻思考一个问题,如何提高后端团队所有人的代码设计能力,确保他们写的代码不会造成服务器宕机。而对 Golang 技术栈的游戏系统来说,这个挑战明显没有那么难了,我们只要确保几个点就可以让程序不会那么轻易宕机。

除了程序本身不轻易宕机之外,我们还要确保系统中没有单点服务,也就是在出现服务不可用的情况,可以由另外一个相同的服务器瞬间接管服务。完全无单点服务很难,这要看服务本身是做什么的,如果是无状态的服务,无单点很好解决,同时启动多个服务,做一个负载均衡就可以解决。但游戏服务很多时候都是有状态的,有状态的服务宕机之后,如何恢复这些状态是一个技术挑战点。如果确实无法避免这些单点服务,那就想想怎么将这些单点服务的影响控制在很小的范围,从整体上看服务依然可用。比如,少三2的游戏服和跨服都是单点服务,游戏服宕机只会影响单个区服,不会影响其他区服,而跨服宕机只会影响跨服玩法,单服内的玩法不受影响。

自动拉起服务,是一个双刃剑。因为游戏服务器是一个有状态的服务,如果宕机时的状态不影响游戏的结果,自动拉起服务可以及时地恢复服务,让玩家能够及时返回游戏场景重新开始游戏,运营层面应该是可以接受的。但如果宕机的状态会影响到游戏的结果,而且必须人工介入处理才能正常恢复状态,那就不能使用自动拉起服务。自动拉起服务还必须配合成熟的报警系统,在自动拉起服务后,运维或研发人员能够及时知晓并上线排查问题,必要时紧急修复问题,避免问题持续影响玩家体验。

4. 避免被第三方掐死

游戏框架中,难免会用到第三方的服务器,比如 sdk 验证、日志、防沉迷系统等等。如果第三方提供的服务不是足够健壮,而代码中不做任何容错的话,你的系统极有可能就会被这些服务掐死。常规的第三方服务,因为具有一定的通用性,所以这些服务基本都是以http协议通信。就拿防沉迷系统来说,做游戏的都知道必须要做,多数情况会是公司级或平台级的部署方案,游戏侧只需要接入就可以了。正常来说,接入也非常简单,玩家登录时先请求平台的验证接口,检查玩家属性(是否未成年人)及其累计游戏时长,如果验证通过则允许登录,之后玩家在线期间则需要定时重新验证及上报游戏时间。如果平台的验证请求都是同步发送,那游戏就会受到平台性能的制约,比如平台因各种原因导致验证接口响应慢了,游戏内的登录体验就会明显变卡,甚至可能造成无法登录的情况。

与第三方服务通信最合理的方法是异步通信,并且在第三方服务无响应或者响应超时的情况下,需要能够跳过这些服务,通过游戏内的本地缓存或兼容算法进行简单处理,等到服务恢复后再重新请求。当然,这要看具体的业务逻辑,比如防沉迷系统,游戏侧完全可以缓存玩家的属性(是否未成年人)和游戏时长,在第三方服务异常的情况下,直接用本地缓存信息进行验证也是可以的,等到服务恢复后再重新进行验证。如果游戏本身已经做的非常好了,但因为第三方猪队友直接被掐死了,那就非常可惜了。

5. 设计防撞墙

任何系统都有一系列最大承载值,系统承载的数值高于阈值,可能会造成性能瓶颈,影响系统服务。当然,这个数值会受到运行环境、系统配置以及设计能力等等的影响。但我们必须正视这些阈值,在游戏 OB 期间关注这些数据,一旦系统运行时这些数值超标,必然会影响游戏体验,甚至会造成系统崩溃。就游戏系统而言,底层影响性能的数值很多,比如:硬件性能(网络带宽、网络IO、磁盘IO、CPU及内存大小等等)、软件性能(最大TCP连接数、网络协议包大小限制、收发包队列长度、存储文件数量及大小、定时器数量、并发线程数等等)。但最终会体现在业务上的性能数值包括:注册人数上限、同时在线人数上限、交互玩法的上限等等,而在游戏 OB 时需要重点考虑的数据就是注册人数和同时在线人数。

一款游戏想要顺利 OB,架构设计者必须对这个数据保持清醒的认知,谨小慎微和盲目自信都是要不得的。而且在游戏 OB 时,仅仅依靠人工关注,是不现实的,你来不及做任何事情,只能眼睁睁的看着服务器被撑爆。按照少三2的级别,OB 开始3分钟内的涌入量绝对在2.5万以上,每分钟的涌入量也都在8000以上,任何分区分服类的游戏都会面临被爆服的可能,如果想做一款比少三2还爆量的游戏,应对难度可想而知。少三2之所以服务器没有被撑爆,是因为我们做了防撞墙,当单服注册人数达到2万或者同时在线人数达到6000时,登录请求会被拒绝,返回客户端错误码,客户端会提示服务器已满,请更换服务器登录。为了避免服务器被挤爆,防撞墙的设计是必须要做的,根据自己系统的设计阈值,对超出阈值的流量做拒绝服务,并做好友好提示。从服务器保护的角度,这个应对是合理的,但从运营的角度,这个应对还远远不够,因为很多小白玩家会因为无法登录游戏直接选择放弃而离开。

少三2防撞设计

6. 设计排队系统

那如何让这些因为超过系统负载而被拒绝的流量不会流失掉呢?在端游时代最常见的排队系统,就是一个很好的方案,让那些小白玩家知道当前系统负载已经满荷,并且告知在他之前还有多少玩家在等待进入,大概还需要等待多久才能够进入游戏,否则流失是必然的。分区分服类的手游也可以做这个,越热门的游戏,OB 时爆量的压力越大,被爆服的可能性越高。另外因为手游 OB 期间,最高同时在线能够达到阈值的时间相对较短,所以手游的排队系统可以设计得简单一些,能够对小白玩家友好一些即可。

少三2排队系统

7. 智能引流系统

面对铁粉,排队系统确实有效,但对于想快速体验游戏的小白来说,那是不够的。他们只想尽快进入游戏,如果游戏体验不是很好,他们可能很快就离开了。因此我们需要智能引流系统,在玩家等待排队时,可以推荐另外一组空闲的服务器,供玩家自由切换。对于分区分服的游戏,在 OB 时,一定会同时开出很多组服务器,供玩家自由选择。但多数情况下,OB 时玩家瞬间涌入,基本都是选择默认服务器进入,如果这个默认服务器不能自动更换,那这台默认服务器必然会被撑爆。如果有一套智能引流系统,在玩家第一次进入游戏时,被防撞墙踢出时,或者在排队系统中等待时,都能被这套智能引流系统引导到一组空闲的服务器,那将会大大降低小白玩家的流失率。

这其实就是一套智能的推荐服务器系统,在登录界面以及排队系统中,能够及时给玩家提供一组空闲的服务器。这就要求这套系统能够实时掌握所有开放服务器的玩家相关数据,包括同时在线人数以及创角人数,能够在这些数据中智能化地找出一组空闲的服务器。

少三2引流系统

少年码上记-微信公众号