很早前即有想法设计一套稳定、高效、安全的弱交互移动网络游戏服务器端基础框架,前些天初步完成简单的初稿文档。第一版设计参考了印象里之前的一些工做经历经验。这些经历经验虽已日渐模糊,但从它们这里,本身获益良多。算法
初稿文档暂只是简单记录了目前想到,或以为比较重要的内容(或许会更新),具体细节等涉及较少。可能我会在业余时间里一点点实现本文所述框架,只是开发计划暂没法预期,毕竟精力颇有限。数据库
一、功能描述编程
1.1) 弱交互移动休闲类游戏服务器端基础框架(以房间为游戏单位,诸如棋牌类游戏)后端
1.2) 相较传统的 MMORPG 服务器框架,简化结构安全
二、框架构成服务器
2.1) LoginGate(登陆网关)网络
运行在公网环境,用于转发客户端与 LoginServer 间的登陆交互等。LoginGate 若是被攻击,可新开其它地址(如在别的机房)的 LoginGate。固然也可部署多个 LoginGate。架构
2.2) LoginServer(登陆服务器)负载均衡
运行在内网环境,只接受合法的 LoginGate 链接,自身也链接至 DBServer,用于客户端登陆验证及登陆状态管理等。框架
2.3) GameGate(游戏网关)
运行在公网环境,主要用于转发客户端与 GameServer 之间的通信封包,同时也能处理诸如外挂、恶意链接等(如新连上来的客户端若 15 秒还不发数据,或如有客户端以非正常速度发数据则直接踢掉甚至加入黑名单)。
一般会有多个 GameGate 进程部署在相同或不一样的物理机上,甚至可部署在不一样的机房。
2.4) GameServer(游戏服务器)
运行在内网环境,游戏逻辑核心服务器,只接受合法的 GameGate 链接,自身也链接至 DBServer,且会经过 UDP 协议发送日志信息给 LogServer 保存。
2.5) DBServer(数据服务器)
运行在内网环境,主要负责游戏数据存取、登陆验证(可选)等逻辑,只接受 LoginServer 与 GameServer 的链接。
2.6) LogServer(日志服务器)
运行在内网环境,用于保存 GameServer(甚至 DBServer、LoginServer 等)经过 UDP 发过来的日志信息。
各服务器间链接图以下。
GameServer、DBServer、LoginServer 及 LogServer 可放在同一局域网甚至同一台物理机上(若是负载不大的话)。经过模块功能划分框架构成,各模块职责明确,代码结构清晰,对于网络攻击防范及减轻譬如 GameServer 的压力等大有裨益。
三、客户端进入游戏流程
3.1) 客户端启动时,向某指定的(固定不变的)地址(域名)发起一个 HTTP 请求,获取 LoginGate 地址(IP&Port)
3.2) 客户端链接至 LoginGate,以后输入帐号密码并提交
3.3) LoginGate 转发帐号密码等信息给 LoginServer,由 LoginServer 验证(与 DBServer 交互)
3.4) 若验证经过,DBServer 准备玩家数据,LoginServer 经过(分布式)负载均衡算法返回某 GameGate 地址,而后 LoginGate 断开和客户端的链接
3.5) 客户端断开与 LoginGate 的链接,并链接至 GameGate
3.6) 客户端经过 GameGate 与 GameServer 创建起链接并进入&开始游戏
四、技术实现
4.1) 开发技术
4.1.1) Golang
游戏后台开发(至少核心及基础框架),用编译型(原生)语言来编写应是比较合理的作法(譬如强类型语法在编译期能提早排除不少可能要到线上运行时才能发现的问题)。动态语言固然也能,但明显这并不是它们所长(如代码组织、代码可读性、调试便利度、部署复杂度以及安全和效率等方面)。
Java 等语言技术固然也能,并且可用的资源不少,人才也很是之多,但它带 VM,部署麻烦,框架厚重,相对而言并不算理想的选择。
C++ 太复杂(即使只用其很小的一部分子集),对人员的技术要求较高(写出稳健的 C++ 程序并不容易),编译太慢,对于中小技术团队来讲并不是好的选择。
而 Delphi,单从其品质中下、人才难寻等方面考虑,更非合适选择。
至于以替代 C++ 为目标的 Rust,综合其语言复杂度(彷佛至今语法还未成型)及开发支持团队、社区、使用案例等,至少短时间内,可能观望一下比较合适。
原生、语法简单且以实用为导向、标准及三方库强大(譬如网络等方面)、编译迅速、编译器优化主流水平(GC 改进已很大且一直在持续改进)、跨平台,说 Golang 是天生的后端开发利器并不为过。
而早已有很多 Web后台、游戏后端、KV数据库等(成功)使用案例。
一般状况下,Golang 能比较快上手,熟悉其它语言技术的开发人员转到 Golang 基本会很快。
4.1.2) Lua(可选)
不止在游戏界,业务逻辑采用脚本语言(较经常使用的是 Lua、Python 等)来开发很是常见,这种方式的好处在于:
4.1.2.1) 灵活,业务逻辑变更可能较频繁,而脚本代码修改执行很方便
4.1.2.2) 划分核心层和业务层,普通开发人员接触不到核心的代码,只能拿到脚本接口文档用脚本写业务逻辑
4.1.2.3) 脚本代码出错了,最多影响局部逻辑(可上报脚本错误以方便后续解决问题),用脚本作一个安全的调用层能够避免整个进程崩溃
4.1.2.4) 热更新
综上,采用 Golang + Lua 相结合的方式,或许不失为可尝试的开发模式。
4.1.3) Protobuf(可选)
高性能的网络传输协议格式,序列化及反序列化速度甚至远胜 JSON、XML 等,其简单、精简(数据描述文件很是小),不依赖于平台,支持多种编程语言。但其实,自实现紧凑高效的封包格式也并不难。
4.1.4) 加解密
PC 网游通常采用 动态加解密模式(编写数套加解密算法并编译,而后抠出每套加解密函数的机器码,每次客户端上线时,随机选取一套加解密算法发给客户端,以后客户端与服务器的通信封包皆经过此算法加解密),但移动游戏估计不容易实现。
若是封包较小且不密集,可考虑采用不对称加解密算法,增长封包破解难度。
否,应考虑 TEA、AES 等对称加解密算法(如 QQ 的聊天信息本质上就是用 TEA 加密的)。
譬如可考虑随机使用几种加解密算法中的一种(每次客户端上线时,服务器经过约定的 ID 告知应使用哪套加解密算法),增长灵活性及破解难度。
4.2) 数据库存储
4.2.1) MySQL Community x64
4.2.2) MongoDB(备选)
4.3) 运行平台
Linux 64bit(CentOS / Red Hat)
五、后记
以上思路,是以单个的游戏为设计立足点,较有局限。
譬如登陆,统一走登陆平台的方式更通行及合理(此时可由 LoginGate 与 平台进行交互验证)。而日志处理等,能有专门的处理后台也不失是好的作法。
只是如此会涉及不少方方面面的细节和作法,于初衷有悖,是以本文所述设计,仅供参考而已。但很明显,基于以上设计,纵使需做扩展,改进起来也较简单(毕竟,此服务器框架专为弱交互移动游戏而设计)。
六、一些讨论
与某基友讨论如斯设计,基友认为无需三层结构(Client-->GameGate-->GameServer),而是让客户端直连 GameServer(GameServer 负责逻辑处理,能够线性扩展),且加一个中央服务器(CenterServer),作简单的游戏状态记录和逻辑处理,以及支配各 GameServer 等。这种设计固然很好,只是在考虑到诸如框架简明及服务器安全等因素,短时间内估计无心以此思路来改动第一版设计。