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掀起了全民直播的热潮.然而个人觉得直播的门槛相对较高,从推流端到服务端器到播放端,无不需要专业的技术来支撑,仅仅推流端就有不少需要学习的知 ...
随机推荐
- [UWP]用Shape做动画(2):使用与扩展PointAnimation
上一篇几乎都在说DoubleAnimation的应用,这篇说说PointAnimation. 1. 使用PointAnimation 使用PointAnimation可以让Shape变形,但实际上没看 ...
- .net 4.0 中的特性总结(三):垃圾回收
1.内存基础知识 每个进程都有其自己单独的虚拟地址空间. 同一台计算机上的所有进程共享相同的物理内存,如果有页文件,则也共享页文件. 默认情况下,32 位计算机上的每个进程都具有 2 GB 的用户模式 ...
- JS性能优化之怎么加载JS文件
IE8+等实行并行下载,各JS下载不受影响,但仍阻塞其他资源下载 如: 图片 所以首要规则就是:将JS放在body底部(推荐) 加载100kb的单个文件比4个25kb的文件快(减少外链文件数量)(脚本 ...
- 关于JS数组的定义
关于js数组的定义的一些内容: 数组是一个对象 只用一个变量,储存多个同类型的信息 数组--连续的储存空间 数组的下标从0开始 ps:定义一个数组可以看作是一个旅馆.里面有很多小房子. 1.创建数组- ...
- SSH连接不上CentOS 主机配置文件导致的原因的解决方法
一.CentOS之SSH的安装与配置 SSH 为 Secure Shell 的缩写,由 IETF 的网络工作小组(Network Working Group)所制定SSH 为建立在应用层和传输层基础上 ...
- Index Scans 索引扫描
官方文档链接地址 http://docs.oracle.com/cd/E11882_01/server.112/e40540/indexiot.htm#CNCPT1170 Index Scans 在索 ...
- PHP运行出现Notice : Use of undefined constant
这些是 PHP 的提示而非报错,PHP 本身不需要事先声明变量即可直接使用,但是对未声明变量会有提示.一般作为正式的网站会把提示关掉的,甚至连错误信息也被关掉 关闭 PHP 提示的方法 搜索php.i ...
- Tomcat常用配置修改
Tomcat常用配置修改 说明 运行需要设置环境变量 JAVA_HOME 即JDK安装目录 tomcat 默认登录地址 http://localhost:8080 配置tomcat 1.端口设置 打开 ...
- Wireshark初步入门
第一次捕获数据包 为了能让Wireshark得到一些数据包,你可以开始你的第一次数据包捕获实验了.你可能会想:"当网络什么问题都没有的时候,怎么能捕获数据包呢?" 首先,网络总是有 ...
- 网络编程学习笔记(三)UDP
1.不可靠的.效率高.数据报(数据打成一个小包一个小包地往外发).非连接. 2.UDP是非连接的,因此严格来说并不区分服务器端和客户端. 3.UDP通信过程:UDP都是通过字节数组进行对话的. ...