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游戲服務器引擎的開發目標是能夠很好地支持常見的MMORPG類游戲。在這類游戲里,玩家往往控制一個角色,並可以在不同的場景之間進行切換,並且通過和周圍的其他對象(包括NPC、怪物、其他玩家等)進行交互進行游戲內容。GoWorld所提供的場景-對象機制能夠很好地支持這些功能。對於其他類似卡牌、棋牌類游戲,也可以使用GoWorld提供的對象機制進行邏輯開發。

 

安裝和運行

下載GoWorld游戲服務器

請前往github下載GoWorld:https://github.com/xiaonanln/goworld/

或者使用go get工具:

go get github.com/xiaonanln/goworld

下載GoWorld依賴的庫

go get -u github.com/xiaonanln/go-xnsyncutil/xnsyncutil
go get -u github.com/xiaonanln/goTimer
go get -u github.com/xiaonanln/typeconv
go get -u golang.org/x/net/context
go get -u github.com/Sirupsen/logrus
go get -u github.com/garyburd/redigo/redis
go get -u github.com/google/btree
go get -u github.com/pkg/errors
go get -u gopkg.in/eapache/queue.v1
go get -u gopkg.in/ini.v1
go get -u gopkg.in/mgo.v2
go get -u gopkg.in/vmihailenco/msgpack.v2
go get -u gopkg.in/natefinch/lumberjack.v2

運行GoWorld測試服務端和客戶端

1. 啟動MongoDB或者Redis作為數據庫

2. 拷貝goworld.ini.sample為goworld.ini,並進行配置

編譯並運行中心分發器(dispatcher)

make dispatcher

components/dispatcher/dispatcher

 

 


還在開發階段,更多內容有待補充,敬請關注 ……

QQ討論群:662182346


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM