Module(模塊)的生命周期
使用leaf開發(fā)游戲服務器由多個模塊組成,模塊的定義如下:
// leaf/module.go
type Module interface{
OnInit()
OnDestroy()
Run(closeSig chan bool)
}
模塊需要實現(xiàn)OnInit(),OnDestroy(),Run(closeSig chan bool)三個接口,這三個接口定義了模塊生命周期的行為.
以官方項目LeafServer為例說明模塊的運行機制
// server/main.go (片段)
// LeafServer程序的入口
func main() {
// ......
leaf.Run(
game.Module,
gate.Module,
login.Module,
)
}
程序入口調用leaf.Run(),在Run函數里面分別注冊了game.Module, gate.Module, login.Module,在leaf源碼里我們可以看到leaf.Run()的行為:
// leaf/leaf.go
func Run(mods ...module.Module) {
// ...
// module
for i := 0; i < len(mods); i++ {
module.Register(mods[i])
}
module.Init()
// ...
// 通過channel c來監(jiān)聽來自操作系統(tǒng)的終止指令
c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt, os.Kill)
// 等待終止指令, 一旦讀到終止指令則執(zhí)行之后的代碼,module.Destroy()將調用各個模塊的OnDestroy()
sig := <-c
// ...
module.Destroy()
}
函數參數mods是我們傳進來的各個模塊,module.Register(mod)將我們的模塊注冊到module中去:
// leaf/module.go
var mods []*module
func Register(mi Module) {
m := new(module)
m.mi = mi
m.closeSig = make(chan bool, 1)
mods = append(mods, m)
}
之后調用module.Init()對我們注冊的模塊進行初始化,進入OnInit()周期,之后對每個模塊開啟goroutine來進入各模塊的Run()周期:
// leaf/module.go
// 初始化
func Init() {
for i := 0; i < len(mods); i++ {
mods[i].mi.OnInit()
}
for i := 0; i < len(mods); i++ {
m := mods[i]
m.wg.Add(1)
// 開啟goroutine
go run(m)
}
}
func run(m *module) {
m.mi.Run(m.closeSig)
m.wg.Done()
}
而Module生命周期的結束階段則在系統(tǒng)讀取到終止命令時執(zhí)行module.Destroy()來進行模塊的銷毀邏輯:
// leaf/module.go
func Destroy() {
for i := len(mods) - 1; i >= 0; i-- {
m := mods[i]
m.closeSig <- true
m.wg.Wait()
destroy(m)
}
}
func destroy(m *module) {
defer func() {
if r := recover(); r != nil {
if conf.LenStackBuf > 0 {
buf := make([]byte, conf.LenStackBuf)
l := runtime.Stack(buf, false)
log.Error("%v: %s", r, buf[:l])
} else {
log.Error("%v", r)
}
}
}()
m.mi.OnDestroy()
}