游戏开发经验谈(一):游戏架构里隐藏的五个坑及其应对方案

游戏开发经验谈(一):游戏架构里隐藏的五个坑及其应对方案

随着移动终端硬件配置的飞速提升,手游行业开始从爆发期进入相对稳定的发展期。残酷市场竞争环境下,游戏公司纷纷寻求业务创新,手游重度化、VR/AR游戏、经典IP回归之外,游戏出海和全球服也成为新亮点。这也意味着云服务需要承载越来越多后端服务器的支撑工作,合理的平台架构将成为系统稳定运行的基础保障。

迄今为止,UCloud平台支持的游戏已经超过了1000余款,其中手游占据了70%以上。在这过程中我们也陪用户踩过了很多“坑”,本文将结合以往的一些经验和成功案例,为大家阐释游戏架构设计上,可能会遇到的一些问题和解决方案。

场景A:All In One的MudOS架构

MudOS是第一代游戏架构,目前应该是无人使用的历史里程碑了,之所以会在这里提到,是因为在云平台,仍然有不少用户使用数据、计算、日志全部集中于同一台服务器的All In One集中式部署架构。

游戏开发经验谈(一):游戏架构里隐藏的五个坑及其应对方案

以当前的技术来说,公有云还没能完全避免宕机对业务造成的影响,而宕机必然要导致业务一段时间内的不可用。一旦出现云主机内部系统崩溃,对于这种架构的服务器更是灾难性的。因为时间和数据都很难保证,最终可能必须通过备份文件才能进行回档。

此外,集中式部署架构对于云主机的性能要求非常高,随着业务的增长,开发者经常要重新调整配置,甚至最后直接购买物理云主机。同时,为了达到过高的性能要求,需要对云产品的硬件灵活性和弹性伸缩能力进行取舍,即使在购买了物理云主机的情况下,云平台的成本优化效果也无法达到最大化。因此,希望大家在游戏设计中规避掉这种集中式部署架构,尽量使用逻辑服或者微服务的模式。

场景B:疯狂掉线

掉线对所有游戏玩家来说都是非常痛苦的事情,我们曾经手过一个疯狂掉线的案例,这个案例的独特之处在于玩家在游戏过程中很少发生卡顿和瞬移问题,但是会经常出现掉线现象,而且还是不定期的玩家集中掉线。掉线的时间点也非常巧合,基本上是在机房监控到DDoS、或者地方级以上骨干容灾切换闪断的时候。

我们初步分析可能是业务和网络的特殊情况触发的,在和用户交流业务逻辑之后,了解到用户的游戏设计采用的是TCP逻辑:业务1分钟发出1个心跳包,如果30秒未收到ACK测试则认为客户端掉线需要重连。很明显,这种设计并没有考虑到丢包或错包等问题。

因为实际情况下,全球运营商的网络设备都有一定的错包率或丢包率,1分钟1个心跳包模式下,一旦发生丢包,玩家在1分30秒内无法收到测试信息,必然会被系统剔除,导致掉线。而在容灾切换或者DDoS情况下,丢包或者错包的问题会更加严重,玩家会集中掉线也就可以解释了。

游戏开发经验谈(一):游戏架构里隐藏的五个坑及其应对方案

定位问题后,我们帮助用户对以上逻辑进行了修改,将玩家的掉线时间从1分30秒收敛成30秒,设置业务每10秒3个心跳包,超过3个周期未收到则视为掉线。 每10秒3个心跳包的情况下,超过30秒就有9个心跳包,只有当这9个心跳包全部丢失,系统才会认为玩家离线。逻辑修改后会形式一个缓冲区,避免错包或丢包情况下造成的系统判断失误。

场景C:单点DB的危机

下图的业务架构设计得已经相对完整,整个系统采用的是DB的主从架构,可能宕机造成的风险都已经规避,唯一的疏漏在于用户将Cache和业务绑定,一旦业务重启,整个Cache就会被清空,同时如果Cache达到上限也造成业务异常。

游戏开发经验谈(一):游戏架构里隐藏的五个坑及其应对方案

有一次用户的DB磁盘异常需要较长时间恢复,雪上加霜的是Cache即将写满,因为更改数据库指向必须重启业务,为了保证游戏的正常运行,又不能把业务切到从库。最后只好联合当时的DBA、内核以及系统专家,耗费大量时间来恢复主库。

为了避免这种情况再次发生,后续用户直接将Cache层拆分出来放到我们的高可用Redis上来保证系统的稳定。

场景D:Redis崩溃

相信做游戏开发的人或多或少都经历过Redis崩溃问题。本案例中,用户采用了比较前沿的框架,它抛弃了传统数据库,直接使用内存存储作为数据的唯一存储器。全球服上使用的是微服务框架,不存在单点风险,业务能力非常强。但因为在研发过程中第一次使用集群化,所以也踩过一些坑。

游戏开发经验谈(一):游戏架构里隐藏的五个坑及其应对方案

问题一:Redis AOF造成短暂查询堆积。 解决方案是进行分片操作,保证AOF时间不一样,将整体业务查询危机缩减下来。此外,针对游戏框架申请DPA,尽量减少刷数据的可能性。 问题二:QPS极限仅能达到数千,甚至出现了不定期慢查询卡死的情况。 查看代码和数据时发现,用户的业务语句中大量使用了KEYS命令且无任何限制,这就类似于在巨大的MySQL集群里select *, 解决方式是直接将所有KEYS风险语句进行调整和范围限制,保证业务的正常运作。 另外,集群Redis是基于proxy和Redis分片实现的,而非集群的原生Redis对短连接的处理性能极差,并且由于单线程的特性,非常容易因为短连接将CPU打满。对于Redis来说,即使提供最强的44核CPU,最后程序运行的结果也是1核跑满,其它43个核围观。

因此,在设计游戏的时候,使用Redis要特别注意两点:1、集群Redis尽量少用Keys命令;2、主备Redis尽量不要使用短连接,因为短连接过多会造成整体业务性下降,尤其在Redis特别集中的环境下,影响会非常严重。

场景E:Register Server 单点

下图为一个实时对战场景的全球服架构,架构采用了自动注册机制,注册服务器类似路由表功能,会保存所有微服务集群的节点IP信息以供业务节点需要时查询调用。架构左侧上层为高可用数据库、高可用内存存储,下方是对战服务器和平台入口,右侧为工会聊天室,框架里面接入了四个对战服。这个框架的稳定性和扩展性都非常强,主机状态对整体业务的影响极小。

游戏开发经验谈(一):游戏架构里隐藏的五个坑及其应对方案

整个框架美中不足的是,最核心的注册服务器采用的是单点,且该服务器串行在整个业务的逻辑中,一旦服务器异常,同样会造成整体业务不可用。如果不做任何修改,在后续上线运维的过程中,不论是因为压力、系统还是其它原因,Register服务器都将会是一个巨大的技术风险。

针对上述问题,我们根据不同的场景推荐了两种不同的解决方案:

管控分离, 通过中心推送+本地缓存机制旁路Register。这种方案适用于调用逻辑较为简单的情况; 影子备份, 配置备用Register Server同步数据并切换。这种方案适用于注册逻辑较为复杂的情况。

总结

本文主要简单介绍了不同场景、不同游戏案例当中遇到的一些框架设计问题和解决方案。下篇文章,将会以对战类全球服游戏为例,重点讲讲游戏架构的设计思路与技术实现。

作者介绍

沈皓:UCloud PathX产品早期方案设计者之一,深耕全球服游戏领域,曾全面负责多个知名游戏的全球/跨国业务对接、部署及落地。对于MOBA、RTS、FPS等各类游戏的出海全球化的需求、难点、架构实现等有独到见解。

转载于:https://my.oschina.net/u/3675312/blog/1922110

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/101504.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • c语言里void什么作用,C语言中void是什么意思?

    c语言里void什么作用,C语言中void是什么意思?C语言中void是什么意思?C语言中“void”表示为无类型,相应的“void*”为无类型指针,常用在程序编写中对定义函数的参数类型、返回值、函数中指针类型进行声明,其作用是对函数返回和参数的进行限定。C语言关键字auto:声明自动变量break:跳出当前循环case:开关语句分支char:声明字符型变量或函数返回值类型const:声明只读变量continue:结束当前循环,开始下一轮循环…

    2022年5月12日
    55
  • java删除数组中指定元素_java学习中如何删除数组中的指定元素「建议收藏」

    java删除数组中指定元素_java学习中如何删除数组中的指定元素「建议收藏」java的api中,并没有提供删除数组中元素的方法。虽然数组是一个对象,不过并没有提供add()remove()或查找元素的方法。这就是为什么类似ArrayList和HashSet受欢迎的原因。不过,我们要感谢ApacheCommonsUtils,我们可以使用这个库的ArrayUtils类来轻易的删除数组中的元素。不过有一点需要注意,数组是在大小是固定的,这意味这我们删除元素后,并不会减少数组的…

    2022年8月11日
    10
  • ERROR running qmake

    ERROR running qmake1>ReadingQtconfiguration(D:/SoftWare/QT5.9.3/5.9.3/msvc2017_64/bin/qmake)1>GHViewerDetect.vcxproj:error:ERRORrunningqmake1>GHViewerDetect.vcxproj:error:qmake:(D:/SoftWare/QT5.9.3/5.9.3/msvc2017_64/bin/qmake)1>GHViewerDetect.vcx

    2022年5月19日
    103
  • 太极阴,阳虚拟框架—-各种插件大总结(烂尾)[通俗易懂]

    太极阴,阳虚拟框架—-各种插件大总结(烂尾)[通俗易懂]最近心血来潮又想起了折腾自己的安卓手机,不由得就想起来了几年前的Xposed框架.于是又开始跃跃欲试起来然而在网上冲浪许久后,虽然人们七嘴八舌但我大概还是看出来了Xposed对于高版本android好像已经不太能用了,更何况我用的还是MIUI于是,我发现了一个新的玩意—-太极框架.(咳,应该也不是啥新东西了只不过我才关注到而已)当然,现在还有好多类似的东西,但这不是我们的主题….

    2022年6月4日
    165
  • GridBagConstraints布局[通俗易懂]

    GridBagConstraints布局[通俗易懂]查看API文档,我们就知道GridBagConstraints有十一个属性!自我感觉API文档里面有些东西讲得不是很好理解,就象gridx与gridy这两个属性一样,有些书上说gridx表示行,gridy表示列!API文档里面更是讲了一大堆。    现在,提供本人对这些属性的理解:  1,  gridx:表示组件的左边缘与网格左部之间的距离,如果学过HTML的话,那么gridx

    2025年10月15日
    3
  • python querystring encode_querystring

    python querystring encode_querystringquerystring(查询字符串)querystring模块提供用于解析和格式化URL查询字符串的实用工具。可以使用以下方式访问它:constquerystring=require(‘querystring’);querystring.decode()新增于:v0.1.99querystring.decode()函数是querystring.parse()的别名。querys…

    2025年8月25日
    3

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号