uniugm/admin/lib/node/node.go

210 lines
5.7 KiB
Go
Raw Normal View History

2025-04-18 17:17:23 +08:00
package node
import (
"admin/lib/xlog"
"admin/lib/xos"
"fmt"
"github.com/gin-gonic/gin"
"sync"
"time"
)
type IBootConfigContent interface {
GetLogConfig() *LogBootConfig
OnReload(first bool, oldContent string)
}
// Node 调度器调度多个app
type Node struct {
// app全局启动参数
bootFlags struct {
globalBootFlag *CommonBootFlags
exBootFlag interface{}
}
// app全局配置文件
bootConfigFile struct {
globalBootConfigFileContent IBootConfigContent // app全局配置文件内容结构体指针为空没有配置文件解析
globalBootConfigParser func(in []byte, out interface{}) error // 配置文件解析函数默认yaml
}
preInitFuncs []pair // 节点node全局的调用方自定义初始化方法早于节点初始化初始化起服配置、日志后
initFuncs []pair // 节点node全局的调用方自定义初始化方法晚于节点初始化初始化起服配置、日志后、早于各个app初始化
postFuncs []pair // 节点node全局的调用方自定义启动所有app之后执行的方法
adis []*ApplicationDescInfo // app的描述信息列表用来生成apps
apps []*Application // 可绑定多个app
tracer *gin.Engine // app全局监控服务为prometheus、pprof共用
}
// NewNode
func NewNode(appOptions ...NodeOption) *Node {
node := new(Node)
node.bootFlags.globalBootFlag = GlobalBootFlags
node.applyOptions(appOptions...)
return node
}
// AddPreInitTask Node自身初始化任务在启动APP逻辑之前执行
func (node *Node) AddPreInitTask(desc string, task Task) *Node {
node.preInitFuncs = append(node.preInitFuncs, pair{desc, task})
return node
}
// AddInitTask Node自身初始化任务在启动APP逻辑之前执行
func (node *Node) AddInitTask(desc string, task Task) *Node {
node.initFuncs = append(node.initFuncs, pair{desc, task})
return node
}
// AddInitTask Node自身初始化任务在启动APP逻辑之前执行
func (node *Node) AddPostTask(desc string, task Task) *Node {
node.postFuncs = append(node.postFuncs, pair{desc, task})
return node
}
// GetBootFlags 获取节点全局的启动参数信息,即./node -node_id 123 -service_name game的值
func (node *Node) GetBootFlags() *CommonBootFlags {
return node.bootFlags.globalBootFlag
}
// GetExBootFlags 获取调用方自定义的全局启动参数
func (node *Node) GetExBootFlags() interface{} {
return node.bootFlags.exBootFlag
}
// GetBootConfigContent 获取注册启动配置文件app.yaml内容
func (node *Node) GetBootConfigContent() IBootConfigContent {
return node.bootConfigFile.globalBootConfigFileContent
}
func (node *Node) applyOptions(options ...NodeOption) *Node {
for _, option := range options {
option.Apply(node)
}
return node
}
// ApplyOptions 应用一些节点配置项
func (node *Node) ApplyOptions(options ...NodeOption) *Node {
node.applyOptions(options...)
return node
}
// WithApp 节点注入app
func (node *Node) WithApp(appDescInfoList ...*ApplicationDescInfo) *Node {
for _, adi := range appDescInfoList {
node.withAppDescInfo(adi)
}
return node
}
func (node *Node) Run() error {
// 初始化node
node.initialize()
defer xlog.CatchWithInfo("run node panic")
// 启动调度器
type waitInfo struct {
desc string
app *Application
err error
}
waitChan := make(chan waitInfo, 1)
// 运行trace server
go func() {
tracerPort := node.bootFlags.globalBootFlag.TracePort
xlog.Noticef("trace server listen on %v", tracerPort)
err := node.tracer.Run(":" + tracerPort)
if err != nil {
waitChan <- waitInfo{"trace server", nil, err}
}
}()
// 初始化各个app
wg := &sync.WaitGroup{}
wg.Add(len(node.apps))
for i, app := range node.apps {
go func(app *Application, initFunc AppInitFunc) {
if initFunc != nil {
err := initFunc(app)
if err != nil {
errInfo := fmt.Errorf("application[%v] init return error[%v]", app.Name, err)
waitChan <- waitInfo{app.Name, app, errInfo}
} else {
xlog.Noticef("application[%v] initialize ok", app.Name)
}
}
wg.Done()
err := app.run()
if err != nil {
// 返回调度器的报错
waitChan <- waitInfo{app.Name, app, err}
}
}(app, node.adis[i].initFunc)
}
// for _, app := range node.apps {
// go func(app *Application) {
// err := app.run()
// if err != nil {
// // 返回调度器的报错
// waitChan <- waitInfo{app.Name, app, err}
// }
// }(app)
// }
wg.Wait()
// 初始化逻辑
for _, j := range node.postFuncs {
curErr := j.value.(Task)()
if curErr != nil {
err := fmt.Errorf("node run post task(%s) return error:%v", j.key, curErr)
panic(err)
}
}
watchSignChan := xos.WatchSignal1()
defer node.Stop()
select {
case signal := <-watchSignChan:
// 优雅停服,监听某些信号
xlog.Noticef("Application receive signal(%v), will graceful stop", signal)
return nil
case errInfo := <-waitChan:
err := fmt.Errorf("Application receive Node(%v) stop with error:%v", errInfo.desc, errInfo.err)
xlog.Errorf(err.Error())
return err
}
}
func (node *Node) Stop() {
for _, app := range node.apps {
app.stop()
}
time.Sleep(3 * time.Second)
}
// WithNode 添加调度器
func (node *Node) withAppDescInfo(adi *ApplicationDescInfo) *Node {
node.adis = append(node.adis, adi)
return node
}
func (node *Node) initApps() error {
for i, app := range node.apps {
if node.adis[i].initFunc != nil {
err := node.adis[i].initFunc(app)
if err != nil {
return fmt.Errorf("application[%v] init return error[%v]", app.Name, err)
} else {
xlog.Noticef("application[%v] initialize ok", app.Name)
}
}
}
return nil
}