有没有golang开发的游戏开发引擎引擎

2016年底的时候对即时通讯以及游戏开发产生了一些兴趣,而且自己这方面的知识掌握也非常少,在未来很多产品应该都会使用到长连接技术(物联网IOT),因此很有必要掌握这方面的技术。于是就在网络上查询相关的资料,但发现目前网络上的开源游戏服务器框架相对较少,而目前市面上已有的一些开源游戏框架又不太对自己的胃口。正好17年初刚回公司的时候事情比较少,就抽时间按照自己对游戏服务器的架构思路做了一套,取名就叫mqant了,现在已经发布到Github上,欢迎大家Fork
为什么决定要重新造一个轮子?
目前网上优秀的开源游戏服务器框架也不少(当然与web框架比起来就少太多了),但总结起来都各有各的优缺点,下面列出我在选型过程中的一些考量,希望大家能开放的讨论,有不恰当的地方也请指正。
首先是开发语言
目前用于游戏服务器开发的主要应该有以下这些语言:
不过我个人不会C++
底层是C 开发语言是lua,
没有客户端库
底层是C++ 开发语言可以使用C#,Python
有多个平台的客户端库
不过我个人不会C#
开发语言是 C#、Python和Lua多种脚本进行开发
有多个平台的客户端库
好像是收费的,但毕竟出名
有多个平台的客户端库
是我最想使用的一种开发语言
开发效率非常高
支持协程,能开发出高并发性的游戏,而且代码可读性好
目前有很多游戏公司应该都使用的是Python作为后端游戏服务器开发语言,有相对成熟的案例
Python很致命的一个问题是进程不能利用多核,也就是说一个进程只能利用一个CPU进行计算,如果要用多核就需要新开进程,这样会造成服务器的维护成本增加,而且开发项目时所需要考虑的问题也更多
可以用来做网关服务器
应该很早就不维护了
没有找到比较好的开源框架
对协程支持不够好
开发效率较低
javascript
1. 语法灵活(这是一把双刃刀,用起来要小心,尤其是团队开发中)
2. 开源库丰富
1. 语法上有一些缺陷
2. 跟Python一样不支持多核
3. 对协程支持不够好,地狱回调很可怕,虽然有一些解决方案,但用起来稍微有点别扭
Pomelo 网易出的,安静了一段时间,最近又开始维护了
有多个平台的客户端库
1. 性能好,跟C/C++/C#一样编译型语言
2. 语法比较简单,开发效率也比较高,接近Python
3. 语言级别支持协程
4. 单进程支持多核并发计算
1. 开源库较少,会golang的开发者比较少
接触的第一个golang框架,设计不错,但不支持多进程
没有客户端库,需要自己实现
cellnet 刚接触,没法评价,但好像它用了callback回调函数的设计,这样的设计在golang应该可以避免
游戏框架的不足
结合个人的实际情况,当时我主要的选择从 skynet Pomelo leaf 这三个框架里面来选择
skynet设计思路非常牛逼,看了风云大牛的设计感觉应该是一个高性能,高稳定性的游戏服务器框架,而且有很多产品已经使用上了。
但个人认为skynet可能也会有以下的两个问题
Actor模式可能对架构能力比较高,不如rpc模式明了
skynet使用第三方网络库的时候可能需要造轮子,要放开膀子开发有些难,跟python tornado的一样,要写出高性能的程序也对开发人员有一定的要求
Pomelo由网易团队开发的,对多进程架构做的非常好,不过由于javascript性能的关系Pomelo的定位也在一些中小型非即时战斗类游戏,经过一段时间的学习和测试,最后还是无奈放弃了
最后经过多方考虑,我选择golang作为开发语言,当时第一个接触的就是leaf,学习开发了一段时间发现了leaf的一些不足
不支持多进程
没有客户端开发库,需要自己造轮子
上面列出来的都是这几个框架的缺点,其实这几个框架都非常优秀,只是不同的需求有不同的要求罢了,希望大家能根据自己实际需求选择最适合自己的框架
对游戏服务器框架的想法
自己心里也对游戏服务器框架有一些自己的想法,最终决定造这个轮子。
高性能,支持多核
这在未来开发,扩展,维护会轻松很多,比如Python这样一台服务器跑上百个进程的游戏服务器,维护起来就很让人头疼
协程在客户端中应用不大,但在服务器开发中可以发挥极大的威力:
高并发,能最大的利用cpu资源
异步开发同步化,免去了回调函数设计,避免了地狱回调
支持分布式,但也支持单进程部署
有些框架写一个demo都需要启动多个进程,实际上在项目前期可能一台服务器就能够支持了,我希望实现一个既可以单进程部署又可以分布式部署的框架
单进程能够实现高性能
分布式部署不用重新设计编码
这个需求的实现主要靠约定,只要开发的时候按分布式环境来开发,代码一般都不需要移植
有丰富的客户端开发库
让开发者专心业务开发,不同再去造轮子了
mqant框架的架构
mqant就是按照以上的思路设计的,同时设计思路上参考了Pomelo,并且也使用了leaf框架的部分代码。
golang本身支持高性能,支持多核
因此mqant的RPC通信都可以按同步来写, 例如:
//远程调用 Login模块的getRand方法
result,err:=m.RpcInvoke("Login","getRand",roomName)
if err==nil{
//getRand 调用成功了,再做下面的远程调用
result,err:=m.RpcInvoke("Login","getName",roomName)
//上面的调用都执行完了才执行下面的代码
result 是远程调用成功以后的返回值
是远程调用失败的信息
以上代码非常清晰,跟普通的函数调用基本一样,但如果用回调函数的话,如下:
m.RpcInvoke("Login","getRand",roomName,func(result string,err string){
if err!=nil{
m.RpcInvoke("Login","getName",roomName,func(result string,err string){
//调用都执行完了才执行下面的代码
支持分布式,但也支持单进程部署
mqant是按模块为单位来划分功能模块的,可以将一组模块放到一个进程来运行,也可以将所有模块放到同一个进程来运行(即单进程模式)
mqant模块间约定按标准的RPC来相互调用
RPC底层分两种模式
1. 基于golang chan的单进程通信
2. 基于rabbitmq的跨进程通信
RPC会根据模块间的部署情况选用适当的通信方式,以达到在单进程模式下RPC通信的最低性能损耗和最快的响应时间
有丰富的客户端开发库
mqant没有考虑帮开发者造一个客户端开发库,而是选用了目前物联网中非常流行mqtt协议来作为通信协议,mqtt本身就有各个平台的客户端开发库,因此可以直接用mqtt的客户端开发库对接到mqant上来。实现了mqant跨平台通信的要求
mqant还是一个非常新的框架,有很多地方都不完善,但我相信有更多大牛的加入进来参与完善和优化的话,mqant框架将变得更好。
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:117024次
积分:1631
积分:1631
排名:千里之外
原创:43篇
评论:63条
(1)(1)(1)(1)(22)(1)(2)(5)(4)(1)(4)有没有实现过cas的golang客户端
因为现在web这块有一部分应用是用beego开发的,网上找资料没有发现用golang实现的客户端,不知道有没有牛人已经实现了,实在不行就只能自己按原理去弄一个了基于Golang的游戏服务器框架cellnet开发日记(二)
| Go语言中文网 | Golang中文社区 | Golang中国
<meta name="author" content="polaris ">
基于Golang的游戏服务器框架cellnet开发日记(二)
基于Golang的游戏服务器框架cellnet开发日记(二)
看官们肯定还有大部分不是很熟悉Actor模型. 我这里基于Erlang, Skynet等语言和框架库来实战型解释下Actor模型.
Actor模型和OO类似, 都是符合人的思维模式进行编码. OO里啥都是类, 用类来模拟对象, 解决所有的问题. Actor类似的使用Actor来模拟处理对象和单元
Actor在Erlang中叫进程(非操作系统进程), 在Skynet中叫svc(服务)
Mailbox消息队列
每个Actor中包含有一个mailbox, 也就是邮箱. Actor自己只能通过收发mailbox与外界进行沟通, 也就是说, Actor之间只能通过消息进行互相交流, 不能采用其他形式.
mailbox本身是一个顺序队列, 先进先出. 而且mailbox从理论上说没有上限, 实际上呢, mailbox可能会由于不断的消息堆积导致内存上涨. 这都是正常的.
既然mailbox是队列, 也就代表着一个Actor里的逻辑处理是顺序的, 单线程的. 但Actor群体中每个Actor可以独立处理事务. 因此CPU可以分到每个Actor中进行处理,并发的大业也就奠定了基础.
Actor的标识: ID
那么, Actor之间的消息要派发, 怎么定位Actor呢? 使用指针?句柄? 都不是的.
Actor定位使用用ID. 每个Actor有全局唯一的ID, 这里不使用GUID, 因为太难定位了, Erlang选择了一种优雅的方式实现ID. 先吃一个栗子:
这就是Erlang的pid(进程id). 点前面的部分代表的是某个独立域, 在这个域中通过序号标示每个进程的id,序号就是小数点后面的部分
那么, 有了ID, 派发消息就变的很简单了, 看栗子
send( 来源id,
目标id, 发送内容)
有来源id的存在, 是为了回发, 或者虚拟来源.
通信自由与部署无关性
有了Actor模型的存在, 逻辑都是分布式编写, 意思就是挂在每个Actor上来编写. 而由于Actor模型之间只有消息通信, 没有函数调用, 指针之类的本地内容. 因此让Actor的部署变的非常自由. 也就是说, Actor的逻辑, 无需关心自己被部署在1个进程, 还是几台机器. 但是为了内部性能和传输效率的考虑. 能不拆进程, 尽量在同一个进程处理, 能不拆到多台机器, 尽量减少拆到多台机器.
但当你确实需要并发时, 只需要轻松的修改下设置或者少量代码, 整个逻辑就可以跑在分布式集群中了
同步和异步
按照Erlang的处理方式, 默认进程(Actor)间使用send发送消息, 这个过程是异步非阻塞的;
当需要同步处理时, 会使用rpc, 也就是使用call的方式进行同步等待, 等对方进程(Actor)收到并处理消息后, 返回结果后, call的调用才结束.
如果call处理中, 其他的Actor给你发消息时, 消息会一直保存在你的Actor的mailbox中, 这里认为mailbox无限大
支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
支持 @ 本站用户;支持表情(输入 : 提示),见
看官们肯定还有大部分不是很熟悉Actor模型. 我这里基于Erlang, Skynet等语言和框架库来实战型解释下Actor模型.
Actor模型和OO类似, 都是符合人的思维模式进行编码. OO里啥都是类, 用类来模拟对象, 解决所有的问题. Actor类似的使用Actor来模拟处理对象和单元
Actor在Erlang中叫进程(非操作系统进程), 在Skynet中叫svc(服务)
Mailbox消息队列
每个Actor中包含有一个mailbox, 也就是邮箱. Actor自己只能通过收发mailbox与外界进行沟通, 也就是说, Actor之间只能通过消息进行互相交流, 不能采用其他形式.
mailbox本身是一个顺序队列, 先进先出. 而且mailbox从理论上说没有上限, 实际上呢, mailbox可能会由于不断的消息堆积导致内存上涨. 这都是正常的.
既然mailbox是队列, 也就代表着一个Actor里的逻辑处理是顺序的, 单线程的. 但Actor群体中每个Actor可以独立处理事务. 因此CPU可以分到每个Actor中进行处理,并发的大业也就奠定了基础.
Actor的标识: ID
那么, Actor之间的消息要派发, 怎么定位Actor呢? 使用指针?句柄? 都不是的.
Actor定位使用用ID. 每个Actor有全局唯一的ID, 这里不使用GUID, 因为太难定位了, Erlang选择了一种优雅的方式实现ID. 先吃一个栗子:
这就是Erlang的pid(进程id). 点前面的部分代表的是某个独立域, 在这个域中通过序号标示每个进程的id,序号就是小数点后面的部分
那么, 有了ID, 派发消息就变的很简单了, 看栗子
send( 来源id,
目标id, 发送内容)
有来源id的存在, 是为了回发, 或者虚拟来源.
通信自由与部署无关性
有了Actor模型的存在, 逻辑都是分布式编写, 意思就是挂在每个Actor上来编写. 而由于Actor模型之间只有消息通信, 没有函数调用, 指针之类的本地内容. 因此让Actor的部署变的非常自由. 也就是说, Actor的逻辑, 无需关心自己被部署在1个进程, 还是几台机器. 但是为了内部性能和传输效率的考虑. 能不拆进程, 尽量在同一个进程处理, 能不拆到多台机器, 尽量减少拆到多台机器.
但当你确实需要并发时, 只需要轻松的修改下设置或者少量代码, 整个逻辑就可以跑在分布式集群中了
同步和异步
按照Erlang的处理方式, 默认进程(Actor)间使用send发送消息, 这个过程是异步非阻塞的;
当需要同步处理时, 会使用rpc, 也就是使用call的方式进行同步等待, 等对方进程(Actor)收到并处理消息后, 返回结果后, call的调用才结束.
如果call处理中, 其他的Actor给你发消息时, 消息会一直保存在你的Actor的mailbox中, 这里认为mailbox无限大
记住登录状态
还不是会员

我要回帖

更多关于 游戏引擎开发教程 的文章

 

随机推荐