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

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

随着移动终端硬件配置的飞速提升,手游行业开始从爆发期进入相对稳定的发展期。残酷市场竞争环境下,游戏公司纷纷寻求业务创新,手游重度化、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

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

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

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • python强制类型转换astype

    python强制类型转换astype在进行将多个表的数据合并到一个表后,发现输出到EXCEL表的数据发生错误,数值型数据末尾都变成了0。这是因为excel数据超过11位,自动以科学计数法显示,其最大处理精度为15位,超过15位,以后数字自动变0。找了一些解决方法,发现用.astype(‘数据类型’)还是挺方便的。我在输出时,将数值型的数据(int)转化成了字符串(str)。使用方法:df.astype(‘数据类型’)  …

  • 如何查看vue版本和vue/cli的版本

    如何查看vue版本和vue/cli的版本经常有人以为vue-V是查看vue的版本,但其实不是,一开始自己迷迷糊糊也以为是,后来查文档之后才知道正确答案,特此在这里总结一下,那么这条博客就当是开启学习vue3之路的第一条笔记叭~如果查看vue版本和vue/cli脚手架的版本,这里共有两种方式:一、命令行vue版本npmlistvuevue/cli版本vue-V部分截图:二、package.json文件查看package.json文件相关依赖版本号:…

  • 详解独立成分分析

    详解独立成分分析最近在学习数据降维的一些方法(有关数据降维的其他内容请看这篇文章),虽然独立成分分析不算是严格意义上的降维方法,但是它和PCA有着千丝万缕的联系,所以打算专门写一篇文章来学习ICA的相关知识,看了挺多的关于ICA的博文,有些文章讲的比较详细。有句话是这么说的:“论文是详细版的知识讲解”,也就是说如果想深入详细的了解某个知识,那么去读相关论文,所以阅读了一篇经典的ICA论文,作者是A.Hyva¨r…

  • 姐姐「建议收藏」

    姐姐「建议收藏」姐姐

  • C#网络编程(Socket编程)「建议收藏」

    C#网络编程(Socket编程)「建议收藏」一、Socket网络编程1.Socket是什么?在计算机通信领域,Socket被译为“套接字”。它是计算机之间进行通信的一种约定或一种方式。通过Socket这种约定可以接收到其他计算机的数据,也可以向其他计算机发送数据。2.本质是编程接口(API),对于TCP/IP的封装,TCP/IP也提供了可供程序员做网络开发所用的接口3.作用Socket的英文原意是“插座”,的意思,通常在计算机编…

  • ubuntu20.04安装opencv_ubuntu opencv安装

    ubuntu20.04安装opencv_ubuntu opencv安装更新源 sudo apt update 安装相关包 sudo apt-get install build-essential cmake git libgtk2.0-dev pkg-config libavcodec-dev libavformat-dev libswscale-dev libjasper 报错:无法定位到 libj…

发表回复

您的电子邮箱地址不会被公开。

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