4

开发者分享:网络游戏避免上线炸服的10个方法

 2 years ago
source link: http://www.gamelook.com.cn/2022/05/484516
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

开发者分享:网络游戏避免上线炸服的10个方法

2022-05-25 • 项目开发管理

【GameLook专稿,未经授权不得转载!】

GameLook报道/对于所有的网络游戏玩家和开发者来说,发布当天都是一次“大考”。通常情况下,无论是通过营销手段还是口碑传播,很多网络游戏发布当天都会涌入大量玩家,而如果开发者没有对此作足够的准备,就很容易“翻车”,导致服务器崩溃,玩家大量流失。

对于网络游戏开发者来说,怎么做才能保证游戏发布的成功呢?在GDC 2022演讲中,来自Pragma Platform Inc公司的CTO Chris Cobb分享了游戏发布当天常见的10个陷阱,并对应给出了解决方案。

以下是Gamelook听译的全部内容:

Chris Cobb:

今天我们主要分享在游戏发布当天把服务器搞崩溃的10种方式,会说一些故事和案例,我是Chris Cobb,担任Pragma公司CTO,Pragma是一个提供在线游戏服务的平台,比如跨平台账号登录、游戏匹配等方面。

lazy.png

我们与全球顶级游戏有合作,包括《英雄联盟》、《命运2》,手游平台有《植物大战僵尸》等。今天我们主要谈的是游戏发布当天可能会出问题的方式。

很多人都经历过这样的问题,这些问题都非常熟悉,不管是开发者还是玩家,都会在游戏发布当天遭遇服务器崩溃或者无法进入游戏的情况,通常情况下这些问题都是由后端支持平台导致,之所以这个问题非常重要,是因为,当玩家们在发布当天遇到服务器问题之后,他们第二天回到游戏里的可能性是未知的。

lazy.png

虽然很难得到确切数字,但至少有60%-70%的玩家如果在发布当天不能玩游戏,他们是不愿意再碰这款游戏的,因此发布当天的服务器稳定性是非常重要的。所以,我们基本上就是分享一些错误的做法,然后分析我们可以对此做些什么。

网络游戏最重要的话题

lazy.png

对于网络游戏来说,最重要的是避免灾难性的错误。第一个主题就是尽早开始,如果把问题拖到研发后期,可能会需要几个月的时间才会解决,如果直到研发最后几个月才测试多人模式,那显然是行不通的。有时候一个项目的研发可能会持续好几年,所以在研发开始的时候解决远比等到截止日期临近好得多。

如果你的工作室转向在线服务,比如季节性的活动、Battle Pass,每周发布一次更新遇到的问题,与每年才会遇到一次的DLC问题不同,比如《命运》或者《火箭联盟》这样经常更新内容的网络游戏,你不能将玩家数据简单的存在服务器上,给游戏打一个补丁然后离开。

你需要考虑的是,如何随着时间不断优化数据,快速在不同版本之间移植数据也是一个挑战,幸运的是,你可以在游戏上线之前进行测试,否则玩家就会成为你的首批测试者。这时候我们就会看到玩家们丢失排位数据、已经获得的内容,比如一个补丁之后,玩家们的账号甚至都被删除,所以尽早开始。

lazy.png

第二个主题是衡量,如果你都没办法观察问题,那就更不用提衡量和解决问题,所以我们需要收集相关功能的数据,通常这分为两个方面,包括总体以及在线运营,比如服务是否能够运行,是否有必备的技术,但我们也需要关注游戏健康度,比如玩家与游戏的互动如何,所以数据是我们找到游戏运行问题的一个方法。

我中途加入了一个团队,他们正在准备发布一个比较大的功能,他们加班到了凌晨三点。第二天早上的时候,我随口问了句这个功能的表现如何,团队里的其他人有些懵懂,然后回答说,应该还可以,目前还没有玩家对这个功能公开提出批评。作为专业人士,这样的结果是不行的,如果等玩家们都开始批评,那时候发现问题就已经晚了。

还有一点是,不要单独解决这个问题,经验是最好的老师,如果你能找到在发布当天遇到过服务器问题的同行,这可能会给你带来帮助。

lazy.png

发布当天让服务器崩溃的10种方法

第一步,没有打造登录序列

lazy.png

游戏发布当天会迎来最多的玩家数量,可能是平均玩家数量的10倍甚至更高,所以这是个流量问题,你的问题并不是解决常规问题,而是当所有人都同时登录的时候该怎么办。比如洛杉矶市区,如果是夜间11点驾车,那是没有问题的,但如果是下午5-7点,简直是噩梦,这对游戏来说简直是灾难。

lazy.png

第一个案例实际上来自于Niantic的《Pokemon Go》,他们曾公开多次分享发布当天遇到的服务器问题,我也曾经在街上玩这款游戏的时候重新加载过几十次。实际上,他们已经发布过在线游戏,《Ingress》也取得过不错的成功,但《Pokemon Go》的用户量比上一款游戏峰值用户的50倍还多。

lazy.png

人们很喜欢抓精灵,这款游戏发布当天遇到了比之前游戏多50倍以上的玩家,但问题在于,他们没有预测到能有这么多玩家,所以没有做登录序列,因此,他们也不知道一次能够体验游戏的用户有多少人。他们没有对此做足够的预案,当一批玩家离开之后,还会有大批玩家接踵而至,所以服务器问题重复发生。

所以,如果你预计发布当天会迎来大量玩家,最好是做一个登录序列,以保证玩家的游戏体验。我们的目标是保护发布当天的顺利,所以就要给预测的用户量预备足够的支持,为此做一个登录序列,但这也带来了第二个问题。

第二步,打造错误的登录序列

lazy.png

不知道为什么,但我觉得大部分的登录序列一开始都是不好用的。我们打造了登录序列,但总会处于不同原因发生问题,就像是我们去机场安检,总会遇到我们不希望看到的排队长龙。

lazy.png

很多时候,我们遇到了问题,并为此打造了登录序列,但上线之后还是失败,这到底是什么原因呢?设计登录序列的时候,我们考虑的是必须限制玩家登录,有时候可能是阻止垃圾账号,包括空白账号,你总会遇到各种现象。

lazy.png

作为开发者,我们在做登录序列的时候就会考虑,我们需要加入什么条件,才能让甄别真实的玩家,就像是参加GDC需要先排队再进门,这是行不通的。我不会展示背后的原因,因为这是个复杂的技术,但会支持一些问题。

你首先需要计算一次允许进入游戏的人数,比如你一次只能支持10万名玩家,你就要为此设计登录序列以保护玩家体验,就像是要计算CCU。另外一个比较容易忽视的问题是,你忘记了计算允许他们进入游戏需要的时间,就像是迪士尼乐园早晨开门,你会遇到很多人,但并不能一次让所有人都进去。

因此设计登录序列的时候,你既需要设计同时进入游戏的玩家人数,还需要了解玩家总数在什么范围,所以,我们需要限制同时玩游戏的用户总量以保持玩家们登录顺利,所以在授权玩家登录之前,你需要搞清楚这个服务的用意。

lazy.png

第三步,没有对平台进行负载测试

当然,你可能做过负载测试,也就是发布当天用真实玩家进行测试,然而这并不是一群非常友好的测试者。我记得一个比较大的发行商在公开测试周末之后发布过一个博客,说他们的服务器一直崩溃,一个好朋友问,为什么不准备足够多的服务器以支撑如此之多的玩家数量呢?这是一个令人很难回答的尴尬问题。

为了不重复,我们简单说一下,你通常会在发布当天遇到更多的玩家数量,所以你的服务器无法满足当时的用户需求,一旦有用户离开,你准备的服务器可能就够用了。

lazy.png

这是个复杂的问题,你测试的目标是想知道发布当天的真实用户压力,我们的目标当然是证明能够支持多少玩家体验游戏。曾有业内大神说过,所有模型都是错的,但其中有些是有用的。

所以,负载测试的目标就是找到一个有用的模式。这里有几种场景,首先是负载测试就是实际发布当天的用户量,最完美的方式就是用真实的玩家数量进行负载测试,然后找到问题有针对性地解决,但你无法提前进行。

因此,你需要模拟发布当天玩家进入游戏的场景,他们到什么地方、访问了商店里的什么东西、通过了哪些玩法。你实际上希望模拟真实用户的游戏内行为,然后在复杂测试中进行规模化扩容。

我们不能通过单个API请求进行模拟就把它运用到50万用户的场景下,你想要打造的是一个有用的模式,想知道玩家们可能会怎么行动,而不是认为他们都做同样的行为。

另一个是负载测试环境,它必须与你的研发环境适应,这包括安全问题、资源等多个方面,你需要提供数据库备份、硬件准备,所有的东西都需要在负载测试的时候齐备。但我们该怎么做到呢?你想要基础设施像写代码那么简单,但实际上每个基础设施都有不同的菜单和控制台,你不可能在另一个环境中完全复制。

你可能会遇到这样的情况,理论上负载测试没有问题,但会因为配置而遇到错误。你不会想要走捷径,因为这和很多至关重要的方面有关。

做《英雄联盟》项目的时候,我们做了并行数据中心追踪一切情况,甚至还有负载测试2,但有时候我们有很多事情要忙,完全把负载测试2给忘记了。有一天我问技术总监,负载测试1怎么样?但他回答说,负载测试1在哪里?最后的结果是,我们不知道在哪个地方丢失了数据中心,实际上我们失去了对整个环境的控制。有时候事情就是如此诡异,管理如此之多的环境非常具有挑战性。

因此我们不得不重新做负载测试2,这浪费了很多时间。所以,你必须对每一个制作环节保持关注,就像是真正的游戏运营一样。尽管最终我们还是解决了问题,但依然是比较具有警示性的。

我们的目标是对准制作环境进行压力测试,不要忽略你在测试过程中对配置做出的任何改动,不要丢掉对测试环境的追踪,因为它有可能代表了你的真实玩家行为。

第四步,做了太多问卷

lazy.png

这是个很普遍的问题,在游戏开始做预测的时候,我们往往会做一些问卷调查,这样做是非常不错的开始方式,你想要做更好的UI,想设计更好的体验,于是你在想,我们最好是呼叫服务器以防某些东西变化。随着时间的变化,这种方法可能是有问题的,因为这就像是呼叫调查。

另一个与《英雄联盟》相关的案例是,我们有工具可以向玩家发送消息,如果有一个服务停掉,他们就可以通过这个工具知道发生了什么,所以你可以直接在某一个区域向50万人直接发送一条信息。

但有一次我们发送了信息之后,再次收到大量玩家请求,试了很多次都是如此。我们在想,到底哪里出了问题?实际上这个功能本身没有问题,但出于某些原因,在玩家收到信息之后,我们的设计是30秒钟之后重置计时器,所以很多是重复呼叫,突然之间,我们设计了一个攻击自己服务的bug。

调查问卷现象是经常会遇到的,这种情况下你尤其需要与工程团队协调,你不能认为只有一个客户端,进而只模拟一对一的网络呼叫,你要设想有100万个客户端,他们每个人都会进行呼叫,这某种程度上需要你改变思考问题的方式。你需要避免这样的问题,因为随着游戏增长,你会遇到大问题。

lazy.png

我们的建议是保持Socket开放,这样你的服务器可以直接给用户发送信息,这样可以带来非常有效的反馈,每次遇到问题的时候,玩家们就会知道发生了什么,但你并不需要每隔几秒就呼叫服务器看发生了什么变化。这样,你就只需要在问题发生的时候才去解决,以打造可以扩容的平台。

所以,对于呼叫服务器,我们应该谨慎使用。

第五步,没有做数据库分片(database sharding)

lazy.png

如果说希望你们从今天的分享中得到什么,这一条我认为是最需要关注的。不知道是什么原因,但很多工程师并不愿意说数据库分片的问题,传统来说,对于很多中小团队,我们没有做数据库分片的技术和资源,但如今支持新硬件比以往更加容易,因此我鼓励同行们尽早在研发中考虑该问题。

lazy.png

单一的数据库会给你带来非常大的瓶颈,即便是扩展了网络服务器,如果所有人同时使用数据库,同样会给你的系统带来很大的压力。这是需要注意的很重要的问题,也是最可能导致游戏崩溃的一个原因。比如此前说到的玩家账号问题之外,用户背包也会给你带来问题。

我们这里可以有多种方式来解决,其中一个就是数据库分片,比如把数据库一分为四,每个分片存储25%的玩家数据,这是个很好的开始方式。还有一个方法是在你的数据库内进行分隔,假设你的游戏有背包、进度、任务和目标,还有Battle Pass、季票等,很容易用一个Jsonclub来存储关键数据。

项目一开始的时候,这是没有问题的,因为那时候你需要存储的数据还比较少,哪怕是内部测试扩大到100人,这个方法也还是有效的。然而在发布当天,这可能是行不通的,即便是当天只有测试期间同样多的用户,把它们分成小组也是有用的。

比如,网络更擅长传输很多小的数据量,而不是庞大的数据。另外,如果你将背包和重新装载分开,意味着你每次发送的数据量就会少很多。玩家购买东西,你只需要处理背包问题,而不需要同时传输很多并没有发生变化的东西。

Pragma合作的很多客户都是大作游戏开发商,他们通常与发行商有协议,在发布当天会有数十万甚至百万用户登陆,我们只有几个月的时间解决所有问题。好消息是,他们都有做登录序列,他们有负载测试,这都是很好,但他们负载测试登录序列的上限是4万人,他们在这个问题上卡住很久。

通过与他们的架构师聊天,我们发现了两个问题。第一个是,他们为所有服务器设计的都是单一的数据库服务器,包括账号、登陆、玩家数据等等,所有数据都打包在一个巨大的方块内。

所以,我们发布当天会有30万用户登陆,发布之后一周会有100万玩家。经过了多次衡量之后,我们决定在工程方面,只做数据库分片,首先是将数据库分割,仅这一个措施就让制作过程中可以保障22万玩家稳定体验游戏,加上登录序列授权,很快就解决了这个问题。

总结来说,你需要分割数据来解锁扩容能力,这样做可以从根本上改变你的平台特性。

第六步,有太多的微型服务

lazy.png

这可能与列表上所有的问题都不一样,尤其是在大公司当中,团队某个部门的一个bug就可能给所有人带来问题,所以你需要解决所有问题,这就很麻烦,所以,让某个团队专门解决某些问题是比较高效率的。

不过,如果走太远,这个方法可能行不通,首先你要先知道,如果对其他服务器的呼叫失败了怎么办?我们之前的想法是,所有服务器都是独立的,每个服务器都可以相应其他服务器的请求,哪怕其他服务器没有响应,你也可以继续自己的服务。

lazy.png

但问题是,如果你的呼叫失败了呢?在游戏里,我们实际上只有一个基础生态系统让玩家体验,通常来说,你并不会控制向其他服务器发送的无效请求,你只想获得需要的数据进行服务,所以不同服务之间是相互影响的。如果一刀切的方式管理太多的微型服务,就会将问题复杂化,通常情况下,一个关键服务挂掉,也会影响其他服务。

这将带来噩梦,每个服务都会优先考虑如何让他们的服务运行,这就会导致大量不同的环境,我碰到过一种情况,有个朋友说,服务器宕机不是他的问题,而是其他服务导致了游戏崩溃,结果每个服务都给出了同样的说法。

这很有趣,但我们都应该知道我们的服务是如何运作的,有太多微型服务经常发生的事,就是一个服务出了问题,就会带来连锁反应。我们想要保持规模,但同时也要目标清晰,在不同服务之间到一个分界线是很有必要的,这样,你就很容易看到某个问题发生在哪个环节。

通常来说5-10个服务就已经让你的团队疲于奔命,如果是20个以上的服务,你会发现很多东西都无迹可寻。

第七步,没有做数据缓存

lazy.png

数据库是一个很有价值的东西,但做数据库比很多方面都慢,缓存就是把我们的数据放在一些更快的位置,让它更容易被获取。

我们与第三方网站合作的时候,很常见的是,他们会在粉丝站创造很多测试账户,这些账户都是机器人,他们试图做出玩家数据,基本来说,我们觉得这是不错的。但问题是,每过几个月我们都会遇到问题,尤其是新的平台进来之后,如果所有的存储都被这些测试账户占用,那么真正的用户就可能会遇到问题。

随后,我们为第三方服务专门做了一个API,做一个所有这些玩家数据的缓存副本,所以,第三方服务可以自行迭代这些数据,它们的变化很慢,这样做让我们避免了服务器崩溃,最终让我们和所有第三都很满意。

我们希望保护自己的数据库,但这就带来了下一个问题:

第八步,使用太多缓存

lazy.png

如我们刚讨论的那样,缓存可以是个很好的工具,但有些时候我们会做过头。如果缓存太多数据,你自己甚至都不清楚某些数据是否已经过时,唯一的方式就是回到数据库验证。但由于优化的东西太多,你会逐渐失去控制,不知道哪些数据来自哪里,让你的团队很难不产生bug的情况下做出改动。

在与一个工作室合作的时候,接入我们的服务之前都很正常,但接入我们的服务之后,他们的服务器发生了崩溃,与之相伴的是,它还摧毁了一些关键服务,比如支付方式处理,这是很奇怪的,我们的服务与支付没有任何关系。

经过我们的调查,我们的服务每秒只发出10-15次请求,对于这样的游戏来说并不是很多。进一步调查之后发现,他们的很多服务实际上没必要做那么大的规模,大量的缓存占据了很多流量,这种情况下,我们共享了支付基础设施服务,就是这么两个毫不相关的服务,给我们带来了很大的痛苦。

我们与他们的团队沟通,比如为什么有这么多的服务,他们给出的理由是为了扩容准备,经过深度挖掘,我们发现团队做了太多的东西,以至于他们自己都无法全部追踪,所以,最后的解决方案是删掉了很多东西,只留了90%的代码。

因此,我们的目标是,你应该衡量和评估优化方案,不要猜测,你很难知道自己做出的改变会带来什么影响。如果你没有某个东西,最好是做一些数据收集工作。这是个很大的话题,但我要长话短说,你要首先问自己,这个功能发布之后,我想要的是什么?通过一系列的问题,找到最能够回答这些问题的答案,然后有选择性的收集数据。

否则,你会遭遇到大量数据,没有人知道这些数据是做什么的、来自哪里、用于什么目的,这会给随后的优化带来非常高的复杂度。

第九步,使用了最新科技

lazy.png

很多人可能知道,项目往往会被推迟,你的游戏可能会因为实用新技术而跳票数月甚至数年。Pragma的原则是,只选择那些有趋势性的技术。

我们合作过一个项目,它所有的匹配都是发生在客户端之外某个平台,一旦这个平台出错,玩家们的客户端也会遇到大量问题,玩家们一直抱怨。我们发现很多技术都是过时的,所以提了一个想法,就是用现代化的技术。

我们希望给玩家带来更好的体验,我们最初的设想是5名工程师耗时几个月完成。但这项目持续了4年,最终用了200人团队来做。发布当天,游戏体验非常粗糙,甚至有些玩家无法进行游戏。性能方面,与我们最初的愿望背道而驰,使用了更多的内存和CPU。

另外是开发者体验,这两个系统实际上使用了完全不同的两个编程语言,你需要切换全新的技术堆栈、研发环境、编程语言,这样才能完成。这是非常极端的案例,最终比我们预期的成本高了100多倍。

分享这个故事的目的是,有时候用新技术取代老技术是没错的,但你需要认真衡量,有时候新技术的代价非常高,当你解决发布当天问题的时候,你必须问自己,最优先的是什么。我们的建议是,使用一些经过规模化验证的技术,这对于游戏发布是很重要的。

比如在Pragma,我们使用的是Java,而很多大公司使用的是MySQL,可能所有人都没有想到,在2022年的今天,很多人还在用1990年代的技术。然而在游戏发布降低风险方面,使用成熟的技术可以带来很大的帮助。

很多工作室的内部工具都是尝试新技术最好的试验田,但当你做游戏发布支持的时候,最好是使用被证明过的技术,这可以让你的游戏发布更成功。

第十步:所有功能植入两次

lazy.png

这里我们说两个现象,一是不断重写功能,还有一个是在代码库里对同一个功能有多种呈现方式。这样的代码库很难维护,会导致很多质量问题,还会影响服务器扩容。我们都知道简单就是最好的,但有时候,过于追求简化也是很困难的。你希望丢掉所有不必要的东西做到极简化,但还要考虑是否有时间去做。

我们讨论过重写的问题,这里谈谈重复代码的问题。这个案例与《英雄联盟》相关,具体说是邀请好友功能,我们加入了验证环节,比如你是否拥有这款游戏,你邀请的人是否玩过《英雄联盟》,基本上,这个代码就是从之前平台复制粘贴的,当我加入的时候,发现很多验证失控现象,这并不是好现象,因为它带来了bug,而且不利于追踪。

随后我们发现,这个代码加入了太多的东西,比如玩家背包,这款游戏共有10个玩家,假设每个人都有50个背包位置,意味着这个代码需要验证很多的东西,才能得到三行代码就能得到的结果。最后,我们将它简化为,检查玩家背包、找到某个东西,然后继续。

这里的目标是,不要自我重复,这样在做出改变的时候就更容易,当你做规模化的时候,也可以带来更多帮助,做起来很困难,但是很值得。

twtc24-1024x492.jpg

以上就是今天分享的全部内容。

如若转载,请注明出处:http://www.gamelook.com.cn/2022/05/484516


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK