五邑隐侠,本名关健昌,10年游戏生涯,现隐居海边。

  本教程以Go语言分区游戏服务端框架搭建为例。

  Go语言是Google开发的一种静态强类型、编译型、并发型、具有垃圾回收功能的编程语言。语法上近似C语言,支持接口、可通过struct包含另一个struct方式实现继承等面向对象的概念。性能上媲美C/C++,相比C/C++更健壮,更易开发并发程序。我以前也写C++服务端,接触Go后,更倾向用Go做游戏服务端开发。

  所谓分区游戏,指游戏将分为很多个区,不同区之间玩家不能互动或只有少量互动。玩家进入游戏需要选择分区,进入指定分区进行游戏,一个玩家可以同时在不同分区有角色。目前市面上大多中重度网络游戏都采用这种模式,分区游戏适合不需要大DAU互动的游戏,如卡牌、MMORPG、SLG等。从技术层面,分区属于集群扩容的一种手段;运营上,有利于分区精细运营,滚服运营已经是比较成熟的游戏运营手段。相对分区游戏,也存在不分区的社交游戏,这类游戏核心玩法是匹配对抗,例如COC。如果把分区游戏的分区,映射为该类游戏的节点服,广播服映射为匹配服,对不分区游戏的架构也就很好理解。

  本教程主要讲分区游戏服务端框架搭建。总体设计如下:

  分区游戏,玩家先登录游戏,然后进入指定分区。所以首先要有一个登录服务器,提供全局的登录服务。登录服务器的核心数据是玩家账号,核心业务是对玩家进行登录校验,包括使用自有账号系统、第三方账号登录。账号数据需要落地长期存储,所以在该服务器配套一个MySQL数据库,用于保存玩家账号信息。有一到多个登录服务进程,进行游戏登录校验。登录服务是一个短连接服务,使用http协议,对外通过nginx提供统一访问地址,对多个登录服务进程做负载均衡。通常,登录接口还会返回分区信息、玩家各分区角色简要信息、客户端最新版本号、配置版本、资源版本、公告等,这些信息可以通过gm服务(后面会介绍)动态更新,登录服在响应请求时获取并返回给客户端。所以在登录服务器会配套一个redis服务,用于这些数据的缓存。

  玩家登录游戏成功后,将进入选定游戏分区。分区是一组服务进程。大部分游戏分区都采用长连接通信,如果同时兼顾现在热门的h5游戏、微信小游戏,考虑选用websocket做通信(以前使用socket)。考虑到游戏中会有广播的需求,广播数据和分区游戏数据都希望从同一个连接返回给客户端,有必要提供一个统一的分区入口网关服,网关服进程对客户端提供统一的分区地址和端口,对内做数据转发。分区的逻辑业务可以集中放在一个游戏服进程里。以前一些游戏,游戏服在线数据会保存在进程内存里,由于游戏数据变化太频繁,MySQL 频繁读写性能不高,所以会隔一定时间才保存到MySQL。但分区内游戏服是一个单点,一旦崩掉,游戏服的内存数据就会丢失,回档到上一次保存的时间。后来一些游戏为了减少这种风险,把在线数据保存到共享内存,再定时保存到MySQL。共享内存依赖系统和语言,目前发现Go没有直接支持。再后来有了memcached和redis,部分游戏选择用这种缓存系统做缓存,游戏服崩掉,数据还在缓存里不会丢失,可以快速启动游戏服恢复服务。我选用redis作为缓存,缓存活跃玩家数据。隔一定时间,把变化数据保存到MySQL。redis数据主要使用key-value方式保存数据,每次业务处理都需要读取、解析,再使用。对业务开发不是很友好。游戏服进程内存还是会保存在线玩家数据,玩家进入分区时从redis读取到游戏服内存,redis不命中则发布消息给数据服进行数据预热,预热成功后从redis读取。后面的请求可以直接通过内存数据做业务判断、处理,更改数据以事务方式保存到redis,成功后响应给客户端。这样内存数据跟redis数据一致,而且可以把玩家数据拆成更细的单元,减少跟redis间的通信。玩家下线后清除游戏服内存数据。所以分区内配套一个redis、一个MySQL。为了建立定时保存数据这个机制,且不会因游戏服崩溃而受影响,配备一个功能很简单的数据服,通过redis的发布订阅机制、消息队列,负责数据的定时落地固化、玩家注册、数据预热。

  前面提到广播服,广播服顾名思义主要负责广播,例如跑马灯广播、世界聊天、世界boss。广播服通过各个分区的网关服将数据广播给玩家,因此广播服将连接各个分区网关。广播任务通过消息队列进行缓存,这样每个分区的广播操作在写到队列后就可以响应客户端。消息队列采用redis实现。广播服是一个全局的服务,为了避免单点风险,可以做成主从,通过redis的订阅发布机制,启动时订阅redis,如果一定时间没有收到发布消息,认为主服务不存在,切换为主服务,取消消息订阅,连接各分区网关,定时向redis发布消息报活。

  除了业务相关的服务,需要对整个服务体系提供管理。例如开服、停服、更新配置/资源版本、发邮件、发公告、发放道具、踢人等。提供一个全局的gm服,各分区服务启动后,游戏服进程连接到gm服并保持心跳,以通知gm服开/停服。gm服将这些变更信息更新到登录服的redis,这样玩家登录游戏就知道各个服的状态。gm服还可以通过向redis发消息通知登录服进行封号等操作。由于各个游戏服都连接到gm服,这样就可以对各个分区发gm命令。gm服可以通过向广播服的消息队列写消息发全员广播。gm服的功能由运营人员进行操作,所以需要提供http服务,方便在网页上访问。gm服有道具发放的功能,所以第三方支付回调可以通过gm服的http接口请求发货。

  为了给运营提供决策,还需要提供统计后台,对游戏数据日志进行收集、统计。由于登录服、各分区的游戏服、gm服都会上报数据,数据来源广,数据量大,需要做消息队列。因此登录服、游戏服、gm服都通过redis的消息队列进行上报。统计服从redis读取消息,保存数据日志到MySQL。因此需要配套一个redis、一个MySQL。统计服的功能由运营人员使用,需要提供http服务,方便在网页上访问。统计服的http接口还支持客户端进行数据上报。

  为了合并运营人员的页面,gm服、统计服通过nginx提供统一的http地址。

  这样就得到了如前面设计图的整个服务框架。

  本篇介绍到这里,接下来会详细介绍各个服务的实现。在此之前,下一篇先介绍一些通用的基础机制设计和实现。

Go游戏服务端框架从零搭建(一)— 架构设计的更多相关文章

  1. 基于Lua的游戏服务端框架简介

    基于Lua的游戏服务端框架简介 [转]https://gameinstitute.qq.com/community/detail/106396 基于lua的游戏服务端框架简介 1. 引言 笔者目前在参 ...

  2. 分享一个C++与Python开发的中小型通用游戏服务端框架(跨平台,开源,适合MMORPG游戏)

    在开发一款游戏项目时,在立项时我们往往会考虑或者纠结很多,比如: 1,对于开发来说:服务端和客户端应该选择什么语言?用什么协议通信才更效率?协议后期如何维护?Socket是用长连接还是短连接?TCP还 ...

  3. 转:云风skynet服务端框架研究

    转:  http://forthxu.com/blog/skynet.html skynet是云风编写的服务端底层管理框架,底层由C编写,配套lua作为脚本使用,可换python等其他脚本语言.sky ...

  4. 《Python》网络编程之客户端/服务端框架、套接字(socket)初使用

    一.软件开发的机构 我们了解的涉及到两个程序之间通讯的应用大致可以分为两种: 第一种是应用类:QQ.微信.网盘等这一类是属于需要安装的桌面应用 第二种是web类:比如百度.知乎.博客园等使用浏览器访问 ...

  5. Node.js服务端框架谁才是你的真爱

    1. Express 背景: Express, 疯一般快速(而简洁)的服务端JavaScript Web开发框架,基于Node.js和V8 JavaScript引擎. Express 是一个基于 No ...

  6. 手游服务端框架之使用Guava构建缓存系统

    缓存的作用与应用场景 缓存,在项目中的应用非常之广泛.诸如这样的场景,某些对象计算或者获取的代码比较昂贵,并且在程序里你不止一次要用到这些对象,那么,你就应该使用缓存. 缓存跟java的Coucurr ...

  7. Java生鲜电商平台-SpringCloud微服务开发中的数据架构设计实战精讲

    Java生鲜电商平台-SpringCloud微服务开发中的数据架构设计实战精讲 Java生鲜电商平台:   微服务是当前非常流行的技术框架,通过服务的小型化.原子化以及分布式架构的弹性伸缩和高可用性, ...

  8. 小程序多端框架全面测评:chameleon、Taro、uni-app、mpvue、WePY

    摘要: 微信小程序开发技巧. 作者:coldsnap 原文:小程序多端框架全面测评 Fundebug经授权转载,版权归原作者所有. 最近前端届多端框架频出,相信很多有代码多端运行需求的开发者都会产生一 ...

  9. 谈一款MOBA游戏《码神联盟》的服务端架构设计与实现

    一.前言 <码神联盟>是一款为技术人做的开源情怀游戏,每一种编程语言都是一位英雄.客户端和服务端均使用C#开发,客户端使用Unity3D引擎,数据库使用MySQL.这个MOBA类游戏是笔者 ...

随机推荐

  1. 模块参数,系统调用,字符设备编程重要数据结构,设备号的申请与注册,关于cdev的API

    1.模块参数  应用编程:      int main(int argc, char *argv[])      {               }      ./a.out xxx yyy zzz  ...

  2. 在ubuntu中编译内核是用make menuconfig报错:package 'ncurses' has n

    执行过程如下: root@zyx-VirtualBox:~# cd /opt/EmbedSky/ root@zyx-VirtualBox:/opt/EmbedSky# cd linux-2.6.30. ...

  3. mysql select自增变量(包括读取当前第几行)

    mysql select自增变量(包括读取当前第几行) SET @rownum =0;select id,@rownum := @rownum +1 as i from ceshi order by ...

  4. day5-基本数据类型总结

    一.数字int(..)二.字符串replace/find/join/strip/startswith/split/upper/lower/format tempalte = "i am {n ...

  5. spring+struts2引起的错误被记忆问题

    标题表述的比较模糊,详细情况是这样的: 目前开发的一个管理系统,当使用出现异常时会自动跳转到错误页.其处理流程是“发生异常——跳转到错误处理action——错误页”. 但是出现了一个bug,即某个操作 ...

  6. 【algo&ds】1.时间复杂度和空间复杂度分析

    1.时间复杂度分析O(f(n)) 分析方法 只关注循环执行次数最多的一段代码 加法原则 乘法原则 高优先级原则 常见时间复杂度量级 多项式量级和非多项式量级.其中,非多项式量级只有两个:O(2^n) ...

  7. Linux运维利器之ClusterShell

    一.简介 实验室机房有大概百台的服务器需要管理,加上需要搭建Hadoop以及Spark集群等,因此,一个轻量级的集群管理软件就显得非常有必要了.经过一段时间的了解以及尝试,最终选择了clustersh ...

  8. nyoj 39-水仙花数

    39-水仙花数 内存限制:64MB 时间限制:1000ms Special Judge: No accepted:35 submit:70 题目描述: 请判断一个数是不是水仙花数. 其中水仙花数定义各 ...

  9. nyoj 170-网络的可靠性 (度为1)

    170-网络的可靠性 内存限制:64MB 时间限制:3000ms 特判: No 通过数:15 提交数:21 难度:3 题目描述: A公司是全球依靠的互联网解决方案提供商,也是2010年世博会的高级赞助 ...

  10. 领扣(LeetCode)转置矩阵 个人题解

    给定一个矩阵 A, 返回 A 的转置矩阵. 矩阵的转置是指将矩阵的主对角线翻转,交换矩阵的行索引与列索引. 示例 1: 输入:[[1,2,3],[4,5,6],[7,8,9]] 输出:[[1,4,7] ...