GoWorld – 用Golang写一个分布式可扩展、可热更的游戏服务器
GoWorld代码:https://github.com/xiaonanln/goworld
Golang具有运行效率高、内存安全等优良特性,因此是非常适合用来进行服务器开发。使用Golang开发游戏服务器有如下的优点:
- 运行效率远高于各种脚本语言,大幅度提升服务器承载能力
- 内存安全,不会像C++服务器那样出现内存错误导致服务器down机
- Goroutine能够很好地利用多核计算能力,提升承载能力
- Golang本身非常简单好用,大家都喜欢
然而使用Golang编写游戏服务器也面临一定的困难,主要是两个方面:
- Golang是静态编译语言,难以为提供方便的语法糖从而简化开发工作
- Golang无法支持语言层面的热更新,可能因为频繁关服带来玩家流失
GoWorld是一个使用Golang实现的可扩展的分布式游戏服务器引擎,并致力于解决以上的这些问题。首先,GoWorld提供对象(Entity)框架来为服务端逻辑开发提供便利。Entity可以在多个场景(Space)之间进行跳转,并且提供AOI支持,因此GoWorld可以很好的支持各种MMORPG游戏服务器所需要的功能。另外一方面,GoWorld通过进程替换来实现游戏逻辑的热更新。在热更新过程中,玩家的客户端连接和各种游戏状态会被保持,并在热更新结束之后恢复正常游戏。
进程结构
GoWorld架构图
一个GoWorld系统包括一个dispatcher进程、一个或者多个game进程以及一个或者多个gate进程。dispatcher负责game之间以及gate和game之间的消息转发,并对一些基础功能提供支持。Game进程负责Entity对象的管理和所有游戏逻辑的运行,Gate进程负责管理客户端连接,并将客户端请求通过dispatcher转发到game进程。Gate还需要负责对客户端数据进行压缩和加解密(尚未实现)。GoWorld可以通过增加更多的game进程或者gate进程来增加服务器的负载能力。虽然dispatcher进程是GoWorld服务器中的单点,但是初步的测试和推算表明一个多核高性能的主机上运行dispatcher可以支持100万以上的同时在线。
热更新
GoWorld使用Hot-Swappaing的方式实现游戏逻辑的热更新。在Game进程收到SIGUSR1信号的时候,就会把当前所有Entity以及其他相关状态保存到一个文件中,并结束进程。此时可以使用最新的可执行镜像重启game进程,并从保存的文件中恢复所有的Entity和游戏状态,并恢复执行。在热更新的过程中,玩家客户端的连接不会中断,玩家角色的状态也会保持不变,只是会感受到一点卡顿,并在热更新结束后恢复。
Entity架构
Entity RPC
在GoWorld中,我们使用一个Entity来代表游戏场景中的玩家、怪物、NPC之类的对象。GoWorld还支持从客户端到服务端的RPC通信,以及服务端Entity之间的RPC通信。
GoWorld在RPC数据的封包和解析上使用了MessagePack格式,并会在将来支持Google Protobuf。
场景
场景(Space)是GoWorld中一个非常重要的概念。每个Entity都属于一个场景。同一个场景的Entity之间可以直接调用相互的函数,而跨场景的Entity之间需要使用RPC来进行通信。Entity可以通过迁移(Migrate)函数来跳转到别的场景中,跳转场景后Entity的所有属性数据都将保持不变。
AOI
GoWorld提供了一套简化的AOI机制。同场景的Entity之间会根据距离维护一个邻居列表。GoWorld使用十字列表维护场景里的所有Entity,从而根据Entity的位置变化实时更新所有Entity的AOI信息。
属性同步
GoWorld为Entity提供了属性机制。属性分为服务端属性、客户端属性和全局属性。服务端属性只有在服务端可以访问,客户端属性可以在客户端和服务端同时访问。每次服务端对其进行修改的时候,属性的变化会立刻被同步到客户端,从而保持客户端数据的实时更新。全局属性是对所有Entity都可见的数据,包括其他玩家。全局属性在发生变化的时候会被广播到AOI范围内的所有玩家,从而使得玩家可以实时获取AOI范围内其他Entity的属性变化。
Entity自动存盘
GoWorld支持Entity的自动存盘。持久化(persistent)的Entity会按一定的时间间隔进行存盘。GoWorld还提供了对已存盘Entity的载入功能。目前GoWorld支持MongoDB和Redis两种不同的底层数据库。
客户端连接和通信
每个server都会创建一个监听端口用于接收来自客户端的连接。客户端和服务端之间也采用一个RPC的通信方式。客户端可以对玩家和玩家AOI里的其他Entity发起RPC调用。
GoWorld支持对客户端通信进行压缩。加密功能还有待添加。。。
还在开发阶段,更多内容有待补充,敬请关注 ……
GoWorld – 用Golang写一个分布式可扩展、可热更的游戏服务器的更多相关文章
- Elasticsearch是一个分布式可扩展的实时搜索和分析引擎,elasticsearch安装配置及中文分词
http://fuxiaopang.gitbooks.io/learnelasticsearch/content/ (中文) 在Elasticsearch中,文档术语一种类型(type),各种各样的 ...
- 使用golang写一个redis-cli
使用golang写一个redis-cli 0. redis通信协议 redis的客户端(redis-cli)和服务端(redis-server)的通信是建立在tcp连接之上, 两者之间数据传输的编码解 ...
- 参考MySQL Internals手册,使用Golang写一个简单解析binlog的程序
GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源. MySQL作为最流行的开源关系型数据库,有大量的拥趸.其生态已经相当完善,各项特性在圈内都有大量研究.每次新特性发布,都会 ...
- Golang 写一个端口扫描器
前话 最近痴迷于Golang这个新兴语言,因为它是强类型编译型语言,可以直接编译成三大平台的二进制执行文件,可以直接运行无需其他依赖环境.而且Golang独特的goroutine使得多线程任务执行如n ...
- golang写一个简单的爬虫
package main import( "fmt" "io/ioutil" "net/http" ) func gethtml(url s ...
- 分布式可扩展存储系统 BaikalDB
BaikalDB是一个分布式可扩展的存储系统,支持PB级结构化数据的随机实时读写. 提供MySQL接口,支持常用的SELECT,UPDATE,INSERT,DELETE语法.提供各种WHERE过滤.G ...
- 用C写一个web服务器(一) 基础功能
.container { margin-right: auto; margin-left: auto; padding-left: 15px; padding-right: 15px } .conta ...
- (原创)如何使用boost.asio写一个简单的通信程序(一)
boost.asio相信很多人听说过,作为一个跨平台的通信库,它的性能是很出色的,然而它却谈不上好用,里面有很多地方稍不注意就会出错,要正确的用好asio还是需要花一番精力去学习和实践的,本文将通过介 ...
- 不用任何第三方,写一个RTMP直播推流器
2016年是移动直播爆发年,不到半年的时间内无数移动直播App掀起了全民直播的热潮.然而个人觉得直播的门槛相对较高,从推流端到服务端器到播放端,无不需要专业的技术来支撑,仅仅推流端就有不少需要学习的知 ...
随机推荐
- Struts+jdbc+分页 实例
根据项目里分页实例,带有注解. package org.tarena.netctoss.dao.impl; import java.sql.Connection; import java.sql.Pr ...
- 织梦dedecms单标签、双标签
标签是dedecms的核心,dedecms的标签也跟html标签一样,同样分单标签和双标签. 我不会讲单标签有那些,双标签有那些,也不会叫大家去背那些是单标签,那些是双标签.如果去背这些标签,这样学起 ...
- C#的命名管道(named pipe)
命名管道是一种从一个进程到另一个进程用内核对象来进行信息传输.和一般的管道不同,命名管道可以被不同进程以不同的方式方法调用(可以跨权限.跨语言.跨平台).只要程序知道命名管道的名字,发送到命名管道里的 ...
- 编写高质量代码:改善Java程序的151个建议(第二章:基本类型)
编写高质量代码:改善Java程序的151个建议(第二章:基本类型) 目录 建议21:用偶判断,不用奇判断 建议22:用整数类型处理货币 建议23:不要让类型默默转换 建议24:边界还是边界 建议25: ...
- redhat 6.8 配置centos6的yum源
1. 检查是否安装yum包[root@node1 rpms]# rpm -qa|grep yum 2. 删除自带的yum包[root@node1 rpms]# rpm -qa|grep yum|xar ...
- 关于MATLAB处理大数据坐标文件2017526
运行六个特征,提高了3分,也就是说以前做的特征已经用完了,穷途末路,依靠以前的特征已经很难取得进步了,提出以下建议 1.测试集曾经运行错误的数据尽早画出图形,并尽可能发现问题并提出特征 2.运行其他程 ...
- 【Android Developers Training】 49. 轻松录制视频
注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...
- 【Android Developers Training】 29. 从Activity获得结果
注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...
- JS实现全选、不选、反选
思路:1.获取元素.2.用for循环历遍数组,把checkbox的checked设置为true即实现全选,把checkbox的checked设置为false即实现不选.3.通过if判断,如果check ...
- Spring框架下的定时任务quartz框架的使用
手头的这个项目需要用到定时任务,但之前没接触过这东西,所以不太会用,从网上找资料,大致了解了一下,其实也不难.Java的定时任务实现有三种,一种是使用JDK自带的Timer那个类来实现,另一种是使用q ...