einx: 一個用Go構建的遊戲伺服器
einx
a framework in golang for game server or app server.
a example server for einx (https://github.com/Cyinx/game_server_einx)
einx 是一個由 golang 編寫的用於遊戲伺服器或者應用伺服器的開源框架。
設計核心:
● 模組與元件的組合機制,模組是邏輯核心。
● lua指令碼
● 按業務分離邏輯
● einx/db 元件化資料庫相關操作
● einx/network 元件化網路IO,目前只支援TCP
● einx/log 非同步日誌庫
● einx/timer 時間輪定時器
● einx/module 模組
● einx/component 元件
● einx/lua 指令碼相關操作
模組與元件
每個模組有且僅有一個goroutine用於處理被投遞到本模組中的訊息,在模組中的邏輯不需要考慮同步問題,簡化了邏輯開發難度,模組與模組之間可以通過RPC互動
使用 einx 搭建一個簡單的伺服器
首先安裝 einx
git clone https://github.com/Cyinx/einx.git
建立一個簡單的einx例子:
package main import ( "github.com/Cyinx/einx" "github.com/Cyinx/einx/slog" ) func main () {
slog. SetLogPath ( "log/game_server/" )
slog. LogInfo ( "game_server" , "start server..." )
slog. LogInfo ( "game_server" , "hello world..." )
einx. Run ()
einx. Close ()
}
einx的核心是module,module中可以新增各種component作為元件:
Cyinx/einx/network網路相關的component
Cyinx/einx/db資料庫相關的component
建立一個TCPServer的component管理器:
package clientmgr import ( "github.com/Cyinx/einx" "github.com/Cyinx/einx/slog" "msg_def" ) type Agent = einx.Agent type AgentID = einx.AgentID type EventType = einx.EventType type Component = einx.Component type ComponentID = einx.ComponentID type ClientMgr struct {
client_map map [AgentID]Agent
tcp_link Component } var Instance = &ClientMgr{
client_map: make ( map [AgentID]Agent),
} func (this *ClientMgr ) GetClient ( agent_id AgentID ) ( Agent , bool ) {client, ok := this.client_map[agent_id] return client, ok
} func (this *ClientMgr ) OnLinkerConneted ( id AgentID , agent Agent ) {
this.client_map[id] = agent //新連線連入伺服器 } func (this *ClientMgr ) OnLinkerClosed ( id AgentID , agent Agent ) { delete (this.client_map, id) //連線斷開 } func (this *ClientMgr ) OnComponentError ( c Component , err error ) {
} func (this *ClientMgr ) OnComponentCreate ( id ComponentID , component Component ) {
this.tcp_link = component
component. Start ()
slog. LogInfo ( "tcp" , "Tcp sever start success" )
}
建立一個邏輯module,並將TcpServer管理器加入到module之中,伺服器就可以啟動,並監聽2345埠的請求
package main import ( "clientmgr" "github.com/Cyinx/einx" "github.com/Cyinx/einx/slog" ) var logic = einx. GetModule ( "logic" ) func main () {
slog. SetLogPath ( "log/game_server/" )
logic. AddTcpServer ( ":2345" , clientmgr.Instance)
slog. LogInfo ( "game_server" , "start server..." )
einx. Run ()
einx. Close ()
}
註冊訊息handler與Rpc: 註冊訊息handler需要事先註冊一個Message:
package msg_def import ( "github.com/Cyinx/einx/network" "protobuf_gen" ) type VersionCheck = pbgen.VersionCheck var VersionCheckMsgID = network. RegisterMsgProto ( uint16 (pbgen.MainMsgID_GENERAL_MSG), uint16 (pbgen.HandlerMsgID_VERSION_CHECK),
(*VersionCheck)( nil ))
在註冊RPC時,使用字串作為RPC名,註冊handler時,需要使用之前註冊的MsgID
import ( "msg_def" ) var logic = einx. GetModule ( "logic" ) func InitDBHandler () {
logic. RegisterRpcHandler ( "testRpc" , testRpc)
logic. RegisterHandler (msg_def.VersionCheckMsgID, CheckVersion)
} func testRpc ( sender interface {}, args [] interface {}) {
} func CheckVersion ( agent Agent , args interface {}) {version_check_msg := args.(*msg_def.VersionCheck)
}
註冊定時器使用module.AddTimer函式,返回值為timerID,如果要提前停止timer,可以執行module.RemoveTimer(timerid):
import ( "msg_def" ) var logic = einx. GetModule ( "logic" ) var testTimerID uint64 = 0 func InitDBHandler () {
logic. RegisterRpcHandler ( "testRpc" , testRpc)
logic. RegisterHandler (msg_def.VersionCheckMsgID, CheckVersion)
} func testRpc ( sender interface {}, args [] interface {}) { if testTimerID != 0 {
logic. RemoveTimer (testTimerID)
}
} func TestTimer ( args [] interface {}) {
testTimerID = 0 } func CheckVersion ( agent Agent , args interface {}) {version_check_msg := args.(*msg_def.VersionCheck)
testTimerID = logic. AddTimer ( 1000 ,TestTimer, 1 , 2 , "測試" )
}
原文釋出時間為:2018-10-29
本文作者:Cyinx
本文來自雲棲社群合作伙伴“ofollow,noindex">Golang語言社群 ”,瞭解相關資訊可以關注“Golang語言社群 ”。