Scalable Distributed Game Server Engine with Hot Swapping in Golang

Overview

GoWorld

Scalable Distributed Game Server Engine with Hot Reload in Golang

GoDoc Build Status Go Report Card codecov ApacheLicense


中文资料

中文文档
游戏服务器介绍
目录结构说明
使用GoWorld轻松实现分布式聊天服务器

游戏服务端开源引擎GoWorld教程

1.安装和运行
2.Unity示例双端联调
3.手把手写一个聊天室
4.多个频道的聊天室
5.登录注册和存储
6.移动同步和AOI
7.源码解析之启动流程和热更新
8.码解析之gate
9.源码解析之dispatcher
10.源码解析之entity


欢迎加入Go服务端开发交流群:662182346


Features

  • Spaces & Entities: manage multiple spaces and entities with AOI support
  • Distributed: increase server capacity by using more machines
  • Hot-Swappable: update game logic by restarting server process
  • Multiple Communication Protocols: supports TCP, KCP and WebSocket
  • Traffic Compression & Encryption: traffic between clients and servers can be compressed and encrypted

Architecture

GoWorld Architecture

Introduction

GoWorld server adopts an entity framework, in which entities represent all players, monsters, NPCs. Entities in the same space can visit each other directly by calling methods or access attributes. Entities in different spaces can call each over using RPC.

A GoWorld server consists of one dispatcher, one or more games and one or more gates. The gates are responsible for handling client connections and receive/send packets from/to clients. The games manages all entities and runs all game logic. The dispatcher is responsible for redirecting packets among games and between games and gates.

The game processes are hot-swappable. We can swap a game by sending SIGHUP to the process and restart the process with -restore parameter to bring game back to work but with the latest executable image. This feature enables updating server-side logic or fixing server bugs transparently without significant interference of online players.

Installing GoWorld

GoWorld requries Go 1.11+ to install.

go get github.com/xiaonanln/goworld/cmd/...

Manage GoWorld Servers

Use command goworld to build, start, stop and reload game servers.

Build Example Chatroom Server:

$ goworld build examples/chatroom_demo

Start Example Chatroom Server: (dispatcher -> game -> gate)

$ goworld start examples/chatroom_demo

Stop Game Server (gate -> game -> dispatcher):

$ goworld stop examples/chatroom_demo

Reload Game Servers:

$ goworld reload examples/chatroom_demo

Reload will reboot game processes with the current executable while preserving all game server states. However, it does not work on Windows.

List Server Processes:

$ goworld status examples/chatroom_demo
> 1 dispatcher running, 1/1 gates running, 1/1 games (examples/chatroom_demo) running
> 	2763      dispatcher      /home/ubuntu/go/src/github.com/xiaonanln/goworld/components/dispatcher/dispatcher -dispid 1
> 	2770      chatroom_demo   /home/ubuntu/go/src/github.com/xiaonanln/goworld/examples/chatroom_demo/chatroom_demo -gid 1
> 	2779      gate            /home/ubuntu/go/src/github.com/xiaonanln/goworld/components/gate/gate -gid 1

Demos

Chatroom Demo

The chatroom demo is a simple implementation of chatroom server and client. It illustrates how GoWorld can also be used for games which don't divide players by spaces.

The chatroom demo provides following features:

  • register & login
  • send chat message
  • switch chatrooms

Build Server:

goworld build examples/chatroom_demo

Run Server:

goworld start examples/chatroom_demo

Chatroom Demo Client:

Chatroom demo client implements the client-server protocol in Javascript.
The client for chatroom demo is hosted at github.com/xiaonanln/goworld-chatroom-demo-client. The project was created and built in Cocos Creater 1.5.

Unity Demo

Unity Demo is a simple multiple player monster shooting game to show how spaces and entities of GoWorld can be used to create multiple player online games.

  • register & login
  • move players in space
  • summon monsters
  • player shoot monsters
  • monsters attack players

Developing features:

  • Hit effects
  • Players migrate among multiple spaces
  • Server side map navigation

Build Server:

goworld build examples/unity_demo

Run Server:

goworld start examples/unity_demo

Unity Demo Client:

Unity demo client implements the client-server protocol in C#. The client for unity demo is hosted at https://github.com/xiaonanln/goworld-unity-demo. The project was created and built in Unity 2017.1.

You can try the demo by downloading GoWorldUnityDemo.zip. The demo connects to a goworld server on Huawei Cloud instance.

Issues
  • go get dependency error

    go get dependency error

    $ go get github.com/xiaonanln/goworld
    # cd .; git clone https://gopkg.in/eapache/queue.v1 
    fatal: unable to access 'https://gopkg.in/eapache/queue.v1/': Unknown SSL protocol error in connection to gopkg.in:-9838
    package gopkg.in/eapache/queue.v1: exit status 128
    fatal: unable to access 'https://gopkg.in/ini.v1/': Unknown SSL protocol error in connection to gopkg.in:-9838
    package gopkg.in/ini.v1: exit status 128
    # cd .; git clone https://gopkg.in/vmihailenco/msgpack.v2 
    fatal: unable to access 'https://gopkg.in/vmihailenco/msgpack.v2/': Unknown SSL protocol error in connection to gopkg.in:-9838
    package gopkg.in/vmihailenco/msgpack.v2: exit status 128
    # cd .; git clone https://gopkg.in/natefinch/lumberjack.v2 
    fatal: unable to access 'https://gopkg.in/natefinch/lumberjack.v2/': Unknown SSL protocol error in connection to gopkg.in:-9838
    package gopkg.in/natefinch/lumberjack.v2: exit status 128
    
    opened by bopjiang 10
  • [unity-demo] Player position not getting set on the server

    [unity-demo] Player position not getting set on the server

    I tried running the unity demo today and it works fine until it doesn't: The player positions does not seem to sync with the server quite right. The packet arrives, but at the wrong entity.

    Somehow during the lifecycle the entity.syncingFromClient property is returning false as the player entity changes (even though the ID stays the same). Furthermore, the player entity seems to get added twice, which probably means we load the same player twice, but don't initialize them correctly - and thus overwrite the existing copy since it's a map.

    opened by spaceemotion 7
  • 感觉像用go抄了一遍messiah server?

    感觉像用go抄了一遍messiah server?

    entity(上述Account,Player都是entity)则可以在space之间进行迁移。entity可以通过EnterSpace调用进入场景,如果这个场景在其他game上,goworld就会将entity的所有属性数据都打包并发送到目标game,然后在目标game上重建这个entity。这个过程对开发者来说是无缝透明的。 同一个space里的所有entity都在同一个game,因此可以直接相互调用。不同space中的entity很可能在不同的game上,因此只能通过rpc相互调用。

    goworld在逻辑开发的时候使用一直单线程事件触发的方式进行开发。game只在主线程(单个goroutine)运行游戏逻辑。 因此任何游戏逻辑都不能调用任何堵塞的系统调用(例如time.Sleep)。单线程的逻辑开发可以大幅度简化逻辑代码的复杂度,因为任何逻辑和数据结构都不需要考虑并发和加锁

    既然是单线程,go的优势完全发挥不出来

    opened by lasorda 4
  • Project directory structure

    Project directory structure

    As I understand you project correctly - it is a framework. So you don't need to have the framework inside your own project, but here I found limitation: project source code should be inside the framework dir. Example: I created my project in ~/test/ I installed goworld framework, installed all deps. goworld with all deps stored in GOPATH, which is different as my project dir. So when I want to build my test project I expect behavior like: goworld build ./test But got:

    • goworld directory found: $GOPATH/src/github.com/xiaonanln/goworld
    • server directory is $GOPATH/src/github.com/xiaonanln/goworld/test Is that behavior is correct? Or what I did wrong?

    Also to cheating that behavior I add symlink inside $GOPATH/src/github.com/xiaonanln/goworld/test to my $HOME/test dir. Building\Starting processes fine, but on stopping - goworld can't find game instance and doesn't stop it and doesn't throw any error.

    opened by KonstantinKuklin 4
  • Code bug?

    Code bug?

    // Choose a dispatcher client for sending Anywhere packets
    func (service *DispatcherService) chooseGameForBootEntity() *gameDispatchInfo {
    
    	if len(service.bootGames) > 0 {
    		gameid := service.bootGames[service.chooseGameIdx%len(service.bootGames)]
    		service.chooseGameIdx += 1
    		return service.games[gameid]
    	} else {
    		gwlog.Errorf("%s chooseGameForBootEntity: no game", service)
    		return nil
    	}
    	gameid := service.bootGames[rand.Intn(len(service.bootGames))]
    	gdi := service.games[gameid]
    	return gdi
    }
    
    opened by github-yxb 3
  • 請教分布式的一些問題

    請教分布式的一些問題

    覺得這種架構挺精實的,很想導入現有專案,所以有些問題想請教。

    1. 在這個架構中不同的Game指的就是不同款遊戲,這樣理解對嗎?

    2. 在這個架構中Space可以理解成是一個遊戲房間嗎?

    3. goworld-chatroom-demo 中的 SendChat 呼叫的是 SendChat_Client 嗎? 怎麼註冊的?

    4. entity 可以藉由 space 屬性對同一個 space 中的其他 entity 做廣播。那能廣播通知給所有同一個 game 的 entity 嗎?

    5. 如果想啟動多個server / 掛ngnix跨機器 的話,有跨server的溝通方案嗎?

    還請作者指點。

    opened by fnaith 2
  • use pktconn

    use pktconn

    pktconn outperforms the existing PacketConnection implementation in GoWorld in both throughput and latency and is better tested.

    Networking latency reduced from ~100ms to ~20ms while using pktconn:

    • Using pktconn
    ===============================================================================
    > DoEnterRandomSpace               *12 AVG 31.679474ms RANGE 36.578197ms ~ 39.285657ms
    > DoSayInWorldChannel              *6 AVG 18.169696ms RANGE 16.115951ms ~ 22.609393ms
    > DoSayInProfChannel               *2 AVG 18.730558ms RANGE 18.204597ms ~ 19.25652ms
    > DoTestComplexAttr                *7 AVG 15.939933ms RANGE 17.665885ms ~ 19.198419ms
    > DoTestCallAll                    *5 AVG 30.375302ms RANGE 27.741105ms ~ 38.140432ms
    > DoTestAOI                        *6 AVG 13.880952ms RANGE 13.166287ms ~ 16.352856ms
    > DoTestListField                  *8 AVG 15.465175ms RANGE 14.520017ms ~ 21.657073ms
    > DoEnterRandomNilSpace            *5 AVG 19.588687ms RANGE 11.402049ms ~ 24.656038ms
    ===============================================================================
    
    • Original:
    ===============================================================================
    > DoTestCallAll                    *4 AVG 195.988074ms RANGE 194.515821ms ~ 197.869241ms
    > DoTestAOI                        *5 AVG 94.045686ms RANGE 90.103806ms ~ 101.137198ms
    > DoTestListField                  *9 AVG 93.991133ms RANGE 90.080405ms ~ 99.492241ms
    > DoTestComplexAttr                *8 AVG 97.600485ms RANGE 92.912506ms ~ 113.727948ms
    > DoEnterRandomNilSpace            *9 AVG 106.968017ms RANGE 90.091706ms ~ 126.201891ms
    > DoSayInProfChannel               *3 AVG 88.898896ms RANGE 90.202709ms ~ 90.584523ms
    > DoEnterRandomSpace               *19 AVG 113.986718ms RANGE 119.16004ms ~ 130.237434ms
    > DoSayInWorldChannel              *6 AVG 89.768127ms RANGE 89.412981ms ~ 94.405859ms
    ===============================================================================
    
    enhancement 
    opened by simonlingoogle 2
  • Mac run errror

    Mac run errror

    hibledeiMac:goworld hible$ /Users/hible/Documents/GoPath/bin/goworld start examples/chatroom_demo

    arguments: start examples/chatroom_demo go search paths: /usr/local/go:/Users/hible/Documents/GoPath goworld directory found: /Users/hible/Documents/GoPath/src/github.com/xiaonanln/goworld info Using config file: /Users/hible/Documents/GoPath/src/github.com/xiaonanln/goworld/goworld.ini {"ts": "2019-07-01T17:53:16.129+0800"} info >>> config <<< debug = true {"ts": "2019-07-01T17:53:16.130+0800"} info >>> config <<< desired dispatcher count = 1 {"ts": "2019-07-01T17:53:16.130+0800"} info >>> config <<< desired game count = 1 {"ts": "2019-07-01T17:53:16.130+0800"} info >>> config <<< desired gate count = 1 {"ts": "2019-07-01T17:53:16.130+0800"} info >>> config <<< storage type = mongodb {"ts": "2019-07-01T17:53:16.130+0800"} info >>> config <<< KVDB type = mongodb {"ts": "2019-07-01T17:53:16.130+0800"} start dispatchers ... dispatcher ids: [1] ! start dispatcher failed, see dispatcher.log for error: fork/exec /Users/hible/Documents/GoPath/src/github.com/xiaonanln/goworld/components/dispatcher/dispatcher: resource temporarily unavailable

    opened by 514366607 2
  • [not an issue] performance measurements

    [not an issue] performance measurements

    Hello,

    First of all, very nice project, keep it up! And second, I have a few questions:

    1. Did you conduct any performance measurements for goworld server?
    2. How many simultaneous client connections it can handle (with one, and multiple gates)?
    3. Does goworld support a 60HZ or 30HZ sync modes, and how many entities it can handle with such rate, (probably disabled encryption/compression) ?
    4. What are the theoretical limitations for the entity amount ?

    And more general question, do you have some sort of text description about your network culling algorithm? As far as I understood you call it Area of Interest.

    Thank you! 👍

    opened by inlife 2
  • 建议考虑支持 client 端的 request-response 模式

    建议考虑支持 client 端的 request-response 模式

    现在 goworld 在 client 端调用 rpc 时候不能支持 request/response 模式,比如:

    const player = client.getPlayer()
    player.callServer("hitBoss", spell, function(result) {
    ...
    })
    

    这种请求应答模式是否考虑支持?这种编程模式在有些场景下开发感觉更简洁。

    opened by luosong 2
  • is it reasonable for goword.GetSpace returing *space object instead of Ispace?

    is it reasonable for goword.GetSpace returing *space object instead of Ispace?

    here is the seene

    type MySpace struct { goworld.Space // Space type should always inherit from entity.Space }

    i create a space called mySpace, if i use func GetSpace(id common.EntityID) *Space i will get an *Space and i can not change it into mySpace unless use mySpace := (*MySpace)(unsafe.Pointer(space))

    and if i change GetSpace into func GetSpace(id EntityID) entity.ISpace { return entity.GetSpaceI(id) }

    then we can easily cast ISpace into mySpace

    ms := goworld.GetSpaceI(monster.Space.ID).(*MySpace)``

    opened by MistarQ 1
  • rpc调用失败

    rpc调用失败

    unity demo可以成功注册Account 但是调用Rpc无效 猜测,ID不统一, 发现 原因是unity中MT_CALL_ENTITY_METHOD_FROM_CLIENT = 12; go里MT_CALL_ENTITY_METHOD_FROM_CLIENT为11; 请问作者还有维护的机会吗=-=

    opened by MistarQ 0
  • @latest found (v0.1.6), but does not contain package

    @latest found (v0.1.6), but does not contain package

    goworld/components/game imports github.com/xiaonanln/goworld/engine/gwvar: module github.com/xiaonanln/[email protected] found (v0.1.6), but does not contain package github.com/xiaonanln/goworld/engine/gwvar goworld/components/game imports github.com/xiaonanln/goworld/engine/kvreg: module github.com/xiaonanln/[email protected] found (v0.1.6), but does not contain package github.com/xiaonanln/goworld/engine/kvreg

    go version go1.16.10 linux/amd64

    opened by flanchegong 0
  • 一定得linux环境吗?Windows Demo跑不通啊?

    一定得linux环境吗?Windows Demo跑不通啊?

    一开始报gameid的错,把他改成1后又报这个错。

    Connect to dispatcher1 failed: dial tcp 127.0.0.1:13001: connectex: No connection could be made because the target machine actively refused it.

    opened by mogebingxue 2
Releases(v0.1.6)
Owner
Nan Lin
Software Engineer
Nan Lin
Arkanoid game in Go using Ebiten game engine with ECS.

Arkanoid-go Arkanoid game in Go using Ebiten game engine with ECS. You must have Git LFS installed when cloning the repository to download assets. See

null 56 Apr 2, 2022
AircraftWar - a game powered by Go+ spx game engine

AircraftWar - a game powered by Go+ spx game engine How to run Download Go+ and build it. See https://github.com/goplus/gop#how-to-build. Download thi

GoPlus 1 Jan 5, 2022
FlappyCalf - a game powered by Go+ spx game engine

FlappyCalf - a game powered by Go+ spx game engine How to run Download Go+ and build it. See https://github.com/goplus/gop#how-to-build. Download this

GoPlus 2 Jan 10, 2022
FlappyCalf - a game powered by Go+ spx game engine

FlappyCalf - a game powered by Go+ spx game engine How to run Download Go+ and build it. See https://github.com/goplus/gop#how-to-build. Download this

GoPlus 2 Jan 10, 2022
MazePlay - a game powered by Go+ spx game engine

MazePlay - a game powered by Go+ spx game engine How to run Download Go+ and build it. See https://github.com/goplus/gop#how-to-build. Download this g

GoPlus 1 Dec 16, 2021
A lightweight and efficient messaging gateway server for distributed game servers, written in Go.

Overview channeld is an open source, light-weight and efficient messaging gateway server designed for distributed game servers (typically MMO) and oth

Sang Tian 9 May 9, 2022
a framework in golang for game server or app server

einx a framework in golang for game server or app server. a example server for einx (https://github.com/Cyinx/game_server_einx) Features User-Friendly

Cyinx 403 Jun 16, 2022
A small fantasy game engine in WASM using GoLang

The GoLang Fantasy Engine (GoLF Engine) is a retro game engine. It draws inspiration from fantasy console projects like pico-8, tic-80, and pyxle. Like those projects it is designed to be a retro-feeling game creation/playing tool. Unlike those projects GoLF is more minimal in scope and only provides an API and a small set of tools to help you create your games. Tools like an image editor and code editor are not built in. Despite this minimalism creating games in GoLF is still easy and should still maintain the retro game feel.

Brandon Atkinson 86 May 25, 2022
golang powered game engine

Gobatch Go powered engine that offers features from low level opengl abstraction to UI framework. I created this to separate lot of logic from game am

Jakub Dóka 43 May 22, 2022
A simple game that I created with Ebiten game library as a way to teach myself Go. Enjoy!

galactic-asteroid-belt Overview A simple game that I created with Ebiten game library as a way to teach myself Go. Enjoy! Run To run, you will need Go

null 0 Dec 2, 2021
RundQuiz-Game - This is a Go exercise that implements and builds a quiz game from a list of math questions in a CSV file.

Go RundQuiz Game Exercise details This exercise is broken into two parts to help simplify the process of explaining it as well as to make it easier to

IkehAkinyemi 0 Jan 5, 2022
Simple 2D game to teach myself various things about game development and ECS, etc

2d-grass-game I really don't know what to name this game. Its a big grass field, and its in 2d so....2D Grass game This is a simple 2D game to teach m

James Wynne III 1 Jan 17, 2022
Engo is an open-source 2D game engine written in Go.

Engo A cross-platform game engine written in Go following an interpretation of the Entity Component System paradigm. Engo is currently compilable for

Engo 1.5k Jun 26, 2022
Go 3D Game Engine

G3N - Go 3D Game Engine G3N (pronounced "gen") is an OpenGL 3D Game Engine written in Go. It can be used to write cross-platform Go applications that

G3N - Go 3D Game Engine Repositories 2k Jun 26, 2022
A pure Go game engine

Oak A pure Go game engine Table of Contents Installation Motivation Features Support Quick Start Implementation and Examples Finished Games Installati

Oakmound Studio 1.2k Jul 1, 2022
Terminal-based game engine for Go, built on top of Termbox

Termloop Termloop is a pure Go game engine for the terminal, built on top of the excellent Termbox. It provides a simple render loop for building game

Joel Auterson 1.3k Jun 17, 2022
A 2D ARPG game engine.

Abyss Engine is an ARPG game engine in the same vein of the 2000's games, and supports playing games similar to Diablo 2. The engine is written in golang and is cross platform. This engine does not ship with game specific files, and will require a game's assets in order to run.

OpenDiablo2 55 Jun 4, 2022
spx - A 2D Game Engine for learning Go+

spx - A 2D Game Engine for learning Go+ Tutorials How to run spx tutorials? Download Go+ and build it. See https://github.com/goplus/gop#how-to-build.

GoPlus 69 Jun 23, 2022
Go Game Engine using SDL for fun

nMage nMage is a (hopefully!) high performance 3D Game Engine written in Go being developed live, with recordings posted on YouTube. This project is b

Omar Mahdi 49 Jun 5, 2022