游戏业务的不停服更新

ronald10个月前职场2980

一. 概述

        前面说到,游戏业务属于内容向的互联网业务,有着运营灵活、内容更新频繁等特点。从玩家游戏体验考虑,游戏的运营方希望做到游戏内容的变更对于玩家来说无感知,也就是做到不停服的游戏更新。游戏更新从更新范围和内容上分为:

        1. 运营版本更新(即常规运营活动的发布)

        2. 紧急版本更新(即现网程序bug和配置错误的紧急修复)

        3. 大版本更新(即月度或者季度大型游戏玩法发布)三类。

       而为了在保证游戏服务不中断的前提下应对上述发布需求各个项目组也研发出各自的系统架构,这里介绍应用比较广的几种:

        1. 基于共享内存和信号处理的游戏进程结构

        2. 基于C++/Lua混合编程的进程结构

        3. 基于流量治理的发布机制

        下面将结合游戏发布场景逐个进行介绍。

二. 基于共享内存和信号处理的游戏进程结构

        游戏业务的更新发布总体上可以分为配置更新和应用程序更新:

    1. 对于配置更新

        是指在游戏进程的底层框架在初始化的时候就进行相关的信号注册,当需要更新的配置分发到进程的配置目录的时候给对应进程发信号,触发进程重载配置的逻辑,进程读取配置之后则新的配置立刻生效。整个过程就相当于重新调用了一个读取配置的接口,整个流程对玩家的游戏体验是无感知的。

    2. 对于程序更新

        本进程结构的做法是:首先将业务层和接入层进行分离,由接入层负责链接的维护,而由业务层进行逻辑的处理,同时应对产品复杂的需求;其次业务层进程将进程数据放在共享内存之中,这样当有程序需要更新的时候,直接重启业务进程,因为数据都是缓存在共享内存中,所以游戏进程重新挂载即可,原先的状态并没有丢失,另一方面链接由接入网关层统一管理,客户端并不会因进程重启而掉线,因而整个过程对于用户无感知。

    这样的游戏进程结构可以应对线上大部分的配置更新和逻辑更新,但是由于游戏进程的数据托管在共享内存中,因此本框架并不能适配于共享内存结构发生变化的发布场景。

三. 基于C++/Lua混合编程的进程结构

        这种结构是利用了脚本语言作为解释性编程语言在程序运行时才进行翻译的特性。底层代码比较稳定不常变动or调用频繁性能要求高的部分由C++代码实现,而其他调用频度不高的业务逻辑交给脚本语言(比如Lua)来实现。在这样的进程结构下,实现逻辑变更可以做到配置变更一样,将对应的Lua脚本通过配置中心将代码像分发配置一样,分发到对应的代码目录下,并给i进程发送信号,触发脚本重载的操作。

    这种进程结构下,逻辑变更相对前者更加轻量,但是也存在一些问题:

     ① C++部分代码变更无法做到支持

     ② Lua的执行性能使得不能应用于对性能要求较高的业务场景


四. 基于流量治理的版本更新机制

        这种更新机制的发展受启发于云原生思想并得益于底层存储组件、通信组件等技术及设计理念的发展。随着存储技术的提升,很多游戏业务的后台进程可以选择利用数据库缓存游戏进程状态,从而使得业务进程可以做到弱状态,甚至完全无状态;而另一方面,随着消息组件的发展,游戏后台系统的进程之间不需要直接对接,而是只需要和底层消息队列建立链接,通过消息队列进行消息收发,使得进程之间由原先的网状和星状结构变成以消息队列为主干的树状结构。

    在此背景下,业务进程的功能被拆分的更细,更加聚焦,如有专门的聊天服务、邮件服务、商城服务等;而对于后台的单一服务,由多个对等进程构建的进程组提供。消息队列通过特定的路由规则,将新的请求分发到进程组中某一个节点上进行处理,此时若是需要某个业务进行更新,则通过将进程组分为A/B组,对其中一组执行下线操作(但是不停进程),则针对后端的无状态路由请求会被派发到未被下线的进程组那里;而由于进程未停止,原先未走完的事务可以通过有状态路由(即指定收包端节点的方式)保证中间态的事务可以顺利完成,当下线后的残留事务完成之后,我们可对这些进程进行停机更新的操作,更新完成顺利上线后另一组同理。

    基于流量治理的版本更新方式,应用面比较广,不仅可应用于配置更新、逻辑更新,还可以应用于数据结构更新的发布场景,甚至可以做到大版本更新也对用户无感知。但是相比前面两种发布机制,流量管理的发布方式操作更重,运维也更加复杂。


后记

        本文介绍了不停服更新的几种方式,以及各自优缺点和适用的场景,当然还有一些其他的不停服更新的机制,比如生成动态链接库等,这里只是挑了几种典型的发布机制进行介绍,不同的项目可以针对自己项目的具体情况、团队的技术栈等,进行对应的架构选型。


相关文章

Lua的Upvalue和闭包(一)

Lua的Upvalue和闭包(一)

upvalue什么是upvalue    Lua的upvalue指的是函数内引用的非全局的外部变量,这么说有两层意思:    1)他是非全局的变量,即这个变量是用local修饰的    2)它是外部变量,即这个变量不是在函数内定义的变量如下代码所示:local test...

后台开发人员面试资源汇总(C&C++方向)

后台开发人员面试资源汇总(C&C++方向)

    汇总一下C/C++后台开发方向的学习资料,为避免广告之嫌,只罗列书名不贴链接了1.编程语言类《C++ Primer》《C 专家编程》《深度探索C++对象模型》《Effective C++:改善程序与设计的55个具体做法》《STL源码剖析》2.操作系统类《鸟哥的Linux私房菜 基础学习篇》《深入理解LINUX内核(第3版)》3.软件工程类《大话设计模...

Lua的Upvalue和闭包(二)

Lua的Upvalue和闭包(二)

Lua闭包和Upvalue的实现    前面文章介绍了Lua闭包和upvalue的概念,本文简单过一下Lua对于闭包和upvalue的实现以加深理解。Lua闭包结构    Lua在内存的结构如下所示:#define ClosureHeader \ CommonHeader; lu_by...

协程-有栈协程(coroutine)

协程-有栈协程(coroutine)

概述    后台架构的微服务化,原先的单体应用被按照功能模块切分为若干进程组承担,此种架构演化带来的收益诸如:单进程复杂度降低,代码维护成本降低发布影响范围缩小,发布灵活性提升计算资源更精准的分配... ...    但是这种架构带来的另外的变化就是,原先由单进程承载的事务,可能涉及几个甚至十几个进程;在这种情况下,采...

Lua的垃圾回收(上)

Lua 5.3版本的垃圾回收垃圾回收算法    垃圾回收算法一般分为两类:引用计数法和标记扫描法。引用计数法    所谓引用计数法,是指在为对象申请内存的时候,在分配的内存块预留一块区域用于存放这块内存被引用的次数,当被引用的时候增一,解引用的时候减一,当这块内存的引用次数降到0的时候,这块内存被认为不可访问,直接被回...

第四次引擎编程尝试

第四次引擎编程尝试

本节我们将尝试在游戏中创建AI,并针根据游戏内的事件做出对应的反应。创建自己的AI类· 按照介绍的,先创建一个我们的AI类,因为AI可以移动、碰撞等,所以我们选择其继承自Character· 创建好AI类之后,我们创建其蓝图类· 创建好蓝图我们进入AI的编辑界面从界面中,我们可以看到:    我们的FPSTpl2AIGuard继承自Character,拥有A...

发表评论    

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。