新手问题 mqant分布式服务器框架设计动机

liangdas · 2017年02月28日 · 388 次阅读

2016 年底的时候对即时通讯以及游戏开发产生了一些兴趣,而且自己这方面的知识掌握也非常少,在未来很多产品应该都会使用到长连接技术 (物联网 IOT),因此很有必要掌握这方面的技术。于是就在网络上查询相关的资料,但发现目前网络上的开源游戏服务器框架相对较少,而目前市面上已有的一些开源游戏框架又不太对自己的胃口。正好 17 年初刚回公司的时候事情比较少,就抽时间按照自己对游戏服务器的架构思路做了一套,取名就叫 mqant 了,现在已经发布到 Github 上,欢迎大家 Fork mqant 开源框架

## 为什么决定要重新造一个轮子?

目前网上优秀的开源游戏服务器框架也不少 (当然与 web 框架比起来就少太多了),但总结起来都各有各的优缺点,下面列出我在选型过程中的一些考量,希望大家能开放的讨论,有不恰当的地方也请指正。

### 首先是开发语言 目前用于游戏服务器开发的主要应该有以下这些语言:

  1. c/c++

    优点:

    性能很好

    缺点:

    不过我个人不会 C++

    开源框架:

    skynet 底层是 C 开发语言是 lua, 没有客户端库

    kbengine 底层是 C++ 开发语言可以使用 C#,Python 有多个平台的客户端库

  2. C#

    优点:

    性能很好

    缺点:

    不过我个人不会 C#

    开源框架:

    Scut 底层 C# 开发语言是 C#、Python 和 Lua 多种脚本进行开发 有多个平台的客户端库

    Photon 底层 C# 好像是收费的,但毕竟出名 有多个平台的客户端库

  3. python

    是我最想使用的一种开发语言

    1. 开发效率非常高
    2. 支持协程,能开发出高并发性的游戏,而且代码可读性好
    3. 目前有很多游戏公司应该都使用的是 Python 作为后端游戏服务器开发语言,有相对成熟的案例

    缺点:

    1. Python 很致命的一个问题是进程不能利用多核,也就是说一个进程只能利用一个 CPU 进行计算,如果要用多核就需要新开进程,这样会造成服务器的维护成本增加,而且开发项目时所需要考虑的问题也更多

    开源框架:

    twisted 可以用来做网关服务器 firefly 应该很早就不维护了

  4. java

    1. 没有找到比较好的开源框架
    2. 对协程支持不够好
    3. 开发效率较低
  5. javascript

    优点:

    1. 语法灵活 (这是一把双刃刀,用起来要小心,尤其是团队开发中) 2. 开源库丰富 缺点:

    1. 语法上有一些缺陷 2. 跟 Python 一样不支持多核 3. 对协程支持不够好,地狱回调很可怕,虽然有一些解决方案,但用起来稍微有点别扭

    开源框架:

    Pomelo 网易出的,安静了一段时间,最近又开始维护了 有多个平台的客户端库

  6. golang

    优点:

    1. 性能好,跟 C/C++/C# 一样编译型语言 2. 语法比较简单,开发效率也比较高,接近 Python 3. 语言级别支持协程 4. 单进程支持多核并发计算

    缺点:

    1. 开源库较少,会 golang 的开发者比较少

    开源框架:

    leaf 接触的第一个 golang 框架,设计不错,但不支持多进程 没有客户端库,需要自己实现 cellnet 刚接触,没法评价,但好像它用了 callback 回调函数的设计,这样的设计在 golang 应该可以避免

### 游戏框架的不足 结合个人的实际情况,当时我主要的选择从 skynet Pomelo leaf 这三个框架里面来选择

skynet 设计思路非常牛逼,看了风云大牛的设计感觉应该是一个高性能,高稳定性的游戏服务器框架,而且有很多产品已经使用上了。 但个人认为 skynet 可能也会有以下的两个问题

  1. Actor 模式可能对架构能力比较高,不如 rpc 模式明了
  2. skynet 使用第三方网络库的时候可能需要造轮子,要放开膀子开发有些难,跟 python tornado 的一样,要写出高性能的程序也对开发人员有一定的要求

Pomelo 由网易团队开发的,对多进程架构做的非常好,不过由于 javascript 性能的关系 Pomelo 的定位也在一些中小型非即时战斗类游戏,经过一段时间的学习和测试,最后还是无奈放弃了

最后经过多方考虑,我选择 golang 作为开发语言,当时第一个接触的就是 leaf,学习开发了一段时间发现了 leaf 的一些不足

  1. 不支持多进程
  2. 没有客户端开发库,需要自己造轮子

上面列出来的都是这几个框架的缺点,其实这几个框架都非常优秀,只是不同的需求有不同的要求罢了,希望大家能根据自己实际需求选择最适合自己的框架

### 对游戏服务器框架的想法 自己心里也对游戏服务器框架有一些自己的想法,最终决定造这个轮子。

  1. 高性能,支持多核

    这在未来开发,扩展,维护会轻松很多,比如 Python 这样一台服务器跑上百个进程的游戏服务器,维护起来就很让人头疼

  2. 支持协程

    协程在客户端中应用不大,但在服务器开发中可以发挥极大的威力:

    1. 高并发,能最大的利用 cpu 资源
    2. 异步开发同步化,免去了回调函数设计,避免了地狱回调
  3. 支持分布式,但也支持单进程部署

    有些框架写一个 demo 都需要启动多个进程,实际上在项目前期可能一台服务器就能够支持了,我希望实现一个既可以单进程部署又可以分布式部署的框架

    1. 单进程能够实现高性能
    2. 分布式部署不用重新设计编码

    这个需求的实现主要靠约定,只要开发的时候按分布式环境来开发,代码一般都不需要移植

  4. 有丰富的客户端开发库

    让开发者专心业务开发,不同再去造轮子了

###mqant 框架的架构

mqant 就是按照以上的思路设计的,同时设计思路上参考了 Pomelo,并且也使用了 leaf 框架的部分代码。

  1. golang 本身支持高性能,支持多核
  2. 支持协程 因此 mqant 的 RPC 通信都可以按同步来写, 例如:

    //远程调用 Login 模块的 getRand 方法 result,err:=m.RpcInvoke("Login","getRand",roomName) if err==nil{ //getRand 调用成功了,再做下面的远程调用 result,err:=m.RpcInvoke("Login","getName",roomName) } //上面的调用都执行完了才执行下面的代码 ....

    result 是远程调用成功以后的返回值 err 是远程调用失败的信息

    以上代码非常清晰,跟普通的函数调用基本一样,但如果用回调函数的话,如下:

    m.RpcInvoke("Login","getRand",roomName,func(result string,err string){ if err!=nil{ m.RpcInvoke("Login","getName",roomName,func(result string,err string){ //调用都执行完了才执行下面的代码 }) } }) ...

  3. 支持分布式,但也支持单进程部署

    mqant 是按模块为单位来划分功能模块的,可以将一组模块放到一个进程来运行,也可以将所有模块放到同一个进程来运行 (即单进程模式)

    mqant 模块间约定按标准的 RPC 来相互调用

    RPC 底层分两种模式

    1. 基于 golang chan 的单进程通信 2. 基于 rabbitmq 的跨进程通信

    RPC 会根据模块间的部署情况选用适当的通信方式,以达到在单进程模式下 RPC 通信的最低性能损耗和最快的响应时间

  4. 有丰富的客户端开发库

    mqant 没有考虑帮开发者造一个客户端开发库,而是选用了目前物联网中非常流行 mqtt 协议来作为通信协议,mqtt 本身就有各个平台的客户端开发库,因此可以直接用 mqtt 的客户端开发库对接到 mqant 上来。实现了 mqant 跨平台通信的要求

### 总结 mqant 还是一个非常新的框架,有很多地方都不完善,但我相信有更多大牛的加入进来参与完善和优化的话,mqant 框架将变得更好。

更多原创文章干货分享,请关注公众号
  • 加微信实战群请加微信(注明:实战群):gocnio
暂无回复。
需要 登录 后方可回复, 如果你还没有账号请点击这里 注册