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写一个分布式可扩展、可热更的游戏服务器的更多相关文章

  1. Elasticsearch是一个分布式可扩展的实时搜索和分析引擎,elasticsearch安装配置及中文分词

    http://fuxiaopang.gitbooks.io/learnelasticsearch/content/  (中文) 在Elasticsearch中,文档术语一种类型(type),各种各样的 ...

  2. 使用golang写一个redis-cli

    使用golang写一个redis-cli 0. redis通信协议 redis的客户端(redis-cli)和服务端(redis-server)的通信是建立在tcp连接之上, 两者之间数据传输的编码解 ...

  3. 参考MySQL Internals手册,使用Golang写一个简单解析binlog的程序

    GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源. MySQL作为最流行的开源关系型数据库,有大量的拥趸.其生态已经相当完善,各项特性在圈内都有大量研究.每次新特性发布,都会 ...

  4. Golang 写一个端口扫描器

    前话 最近痴迷于Golang这个新兴语言,因为它是强类型编译型语言,可以直接编译成三大平台的二进制执行文件,可以直接运行无需其他依赖环境.而且Golang独特的goroutine使得多线程任务执行如n ...

  5. golang写一个简单的爬虫

    package main import( "fmt" "io/ioutil" "net/http" ) func gethtml(url s ...

  6. 分布式可扩展存储系统 BaikalDB

    BaikalDB是一个分布式可扩展的存储系统,支持PB级结构化数据的随机实时读写. 提供MySQL接口,支持常用的SELECT,UPDATE,INSERT,DELETE语法.提供各种WHERE过滤.G ...

  7. 用C写一个web服务器(一) 基础功能

    .container { margin-right: auto; margin-left: auto; padding-left: 15px; padding-right: 15px } .conta ...

  8. (原创)如何使用boost.asio写一个简单的通信程序(一)

    boost.asio相信很多人听说过,作为一个跨平台的通信库,它的性能是很出色的,然而它却谈不上好用,里面有很多地方稍不注意就会出错,要正确的用好asio还是需要花一番精力去学习和实践的,本文将通过介 ...

  9. 不用任何第三方,写一个RTMP直播推流器

    2016年是移动直播爆发年,不到半年的时间内无数移动直播App掀起了全民直播的热潮.然而个人觉得直播的门槛相对较高,从推流端到服务端器到播放端,无不需要专业的技术来支撑,仅仅推流端就有不少需要学习的知 ...

随机推荐

  1. Java之戳中痛点 - (7)善用Java整型缓存池

    先看一段代码: package com.test; import java.util.Scanner; public class IntegerCache { public static void m ...

  2. JVM高级特性-一、java内存结构区域介绍

    区域划分: java虚拟机在执行程序的过程中,将内存分为功能不同的几个区域,如下图: 此图列出了内存划分的各个区域,其中 线程私有的:程序计数器.虚拟机栈.本地方法栈 线程共享的:堆.方法区 下面,逐 ...

  3. Bash内置命令exec和重定向

    Bash内置命令exec可以替换当前程序而不需要启动一个新的进程,可以改变标准输入和输出而不需要启动一个新的子进程.如果文件用exec打开,read命令就会把文件指针每次指向下一行直到文件的末尾,如果 ...

  4. js前端实现多图图片上传预览

    <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="C ...

  5. 第二章完结,包含exam练习

    正则方程(Normal Equation) 梯度下降是最小化代价函数\(J(\theta)\)的一种方式,这里提出了另一种方式即正则方式不使用迭代方式:\(\theta = (X^TX)^{-1}X^ ...

  6. AngularJS高级程序设计读书笔记 -- 指令篇 之 自定义指令

    2. 自定义指令(15-17 章) Module.directive(name, factory) 2.1 创建自定义指令的方法 Module.directive(name, factory) 示例 ...

  7. ubuntu忽然不能登录,输入密码正确一直返回登录界面

    问题描述 由于配置eclipse命令启动,我修改了 /etc/environment 文件的内容,用命令 shutdown -r -now 重启后,输入密码正确一直返回登录界面. 查了下网上资料:系统 ...

  8. [css 实践篇] CSS box-orient

    定义和用法 box-orient 属性规定框的子元素应该被水平或垂直排列. 提示:水平框中的子元素从左向右进行显示,而垂直框的子元素从上向下进行显示.不过,box-direction 和 box-or ...

  9. war包中少了class文件

    用eclipse的maven工具打包(执行mvn clean install  和   mvn package)后,再启动wildfly, war包应该会自动复制到wildfly的deployment ...

  10. python可视化--matplotlib

    matplotlib在python中一般会与numpy同时出现,解决一些科学计算和数据的可视化问题. matplotlib其实就是matlib在python中的实现,因此不会有太大的难度,而由于pyt ...