Documentation
¶
Index ¶
- Constants
- func AddDynamicModules(mods ...IModule) error
- func DynamicModules() []string
- func GetChanRPC(name string) *chanrpc.Server
- func GetState() int32
- func Register(mods ...IModule) error
- func RemoveDynamicModule(name string) bool
- func Run(mods ...IModule)
- func Stats() string
- type IModule
- type IRPC
- type ITimer
- type Skeleton
- func (s *Skeleton) AccTimer(id int64, kind timermgr.AccKind, value int64) error
- func (s *Skeleton) AsyncCall(mod string, req any, cb chanrpc.Callback) error
- func (s *Skeleton) Call(mod string, req any) *chanrpc.RetInfo
- func (s *Skeleton) CancelTimer(id int64)
- func (s *Skeleton) Cast(mod string, req any)
- func (s *Skeleton) ChanRPC() *chanrpc.Server
- func (s *Skeleton) DelayTimer(id int64, kind timermgr.AccKind, value int64) (err error)
- func (s *Skeleton) Name() string
- func (s *Skeleton) NewTicker(id int64, duraMs int64, kind string, metadata map[string]string) int64
- func (s *Skeleton) NewTimer(duraMs int64, kind string, metadata map[string]string) int64
- func (s *Skeleton) OnStart(ctx context.Context)
- func (s *Skeleton) RegisterChanRPC(msg any, f chanrpc.Handler) error
- func (s *Skeleton) RegisterTimer(kind string, handler timermgr.TimerHandler)
Constants ¶
const ( AppStateNone = iota // 应用未启动或已完全停止,可安全重新启动 AppStateInit // 应用正在初始化,所有模块的 OnInit 正在按序执行 AppStateRun // 应用运行中,所有模块已成功启动并处于活跃状态 AppStateStop // 应用正在优雅关闭,模块正按逆序依次停止 )
应用全局状态常量,表示应用生命周期的各个阶段。
Variables ¶
This section is empty.
Functions ¶
func AddDynamicModules ¶
AddDynamicModules 向运行中的全局默认应用实例动态添加并启动一批模块。
动态模块支持热加载,模块在 OnInit 成功后立即启动,无需重启整个应用。 动态模块的 panic 不会导致进程退出,且可通过 RemoveDynamicModule 单独卸载。
func DynamicModules ¶
func DynamicModules() []string
DynamicModules 返回全局默认应用实例中当前所有动态模块的名称列表。
用于运维监控、热加载管理等场景,列表顺序不保证与注册顺序一致(sync.Map 无序)。
func GetChanRPC ¶
GetChanRPC 通过模块名称获取对应模块的 ChanRPC 服务端,用于跨模块消息投递。
优先在静态模块中查找,未命中则查找动态模块。 返回 nil 表示对应模块不存在或不支持 RPC,调用方可据此做降级处理(如 Cast 时静默丢弃)。
func GetState ¶
func GetState() int32
GetState 获取全局默认应用实例的当前运行状态。
返回值为 AppStateNone/AppStateInit/AppStateRun/AppStateStop 之一, 可用于在关闭信号处理逻辑中判断当前是否可以安全发起操作。
func Register ¶
Register 向全局默认应用实例注册静态模块。
必须在 Run 调用之前完成注册。若应用已处于运行状态则返回错误。 运行中需要动态增减模块请使用 AddDynamicModules 和 RemoveDynamicModule。
func RemoveDynamicModule ¶
RemoveDynamicModule 从全局默认应用实例中同步移除并销毁指定名称的动态模块。
操作为同步阻塞:cancel(发停止信号)→ wg.Wait(等待 goroutine 退出)→ OnDestroy(清理资源)→ 从 map 移除。 调用方会等待模块完全停止后才返回,确保所有资源在函数返回前已被完整清理。
Types ¶
type IModule ¶
type IModule interface {
Name() string // 模块唯一名称,用于日志标识和跨模块 RPC 寻址
OnInit() error // 模块初始化,任一模块失败则终止整个应用启动流程
OnStart(ctx context.Context) // 模块主循环,应监听 ctx.Done() 并在收到取消信号时退出
OnDestroy() // 模块销毁,在 goroutine 完全退出后调用,负责释放所有资源
ChanRPC() *chanrpc.Server // 返回模块的 ChanRPC 服务端,nil 表示该模块不接受外部 RPC 调用
}
IModule 定义应用模块的完整生命周期接口。
框架通过此接口管理模块从初始化到销毁的全过程,每个模块代表一个独立的业务单元, 拥有独立的 goroutine、RPC 服务端和定时器管理器。 模块之间通过 ChanRPC 通信,天然隔离内部状态,无需跨模块加锁。
type IRPC ¶
type IRPC interface {
// Cast 单向消息投递,不等待结果,适合日志上报、事件通知等不需要响应的场景。
Cast(mod string, req any)
// Call 同步 RPC 调用,阻塞等待对端处理完成并返回结果。
// 警告:若调用链形成环(A→B→A),将导致死锁,生产环境应优先使用 AsyncCall。
Call(mod string, req any) *chanrpc.RetInfo
// AsyncCall 异步 RPC 调用,立即返回,结果通过 cb 回调在调用方 goroutine 处理。
// 回调在事件循环中串行执行,可安全访问模块内部状态,无需加锁。
AsyncCall(mod string, req any, cb chanrpc.Callback) error
}
IRPC 定义跨模块 RPC 调用的接口,提供三种调用语义覆盖不同并发场景。
调用模式对比:
- Cast:单向投递,无响应,吞吐最高,适合通知/事件
- AsyncCall:异步调用,回调在调用方 goroutine 执行,无锁安全,推荐使用
- Call:同步阻塞,有死锁风险,仅在确认无循环依赖时使用
type ITimer ¶
type ITimer interface {
// RegisterTimer 注册指定类型定时器的处理函数,同 kind 仅能注册一个处理器(后注册覆盖前者)。
RegisterTimer(kind string, handler timermgr.TimerHandler)
// NewTimer 创建一次性定时器,duraMs 毫秒后触发一次,返回定时器 ID。
NewTimer(duraMs int64, kind string, metadata map[string]string) int64
// NewTicker 创建周期性定时器,每隔 duraMs 毫秒触发一次,返回定时器 ID。
NewTicker(duraMs int64, kind string, metadata map[string]string) int64
// AccTimer 加速指定定时器,提前其触发时间。
AccTimer(id int64, kind timermgr.AccKind, value int64) error
// DelayTimer 延迟指定定时器,推迟其触发时间。
DelayTimer(id int64, kind timermgr.AccKind, value int64) (err error)
// CancelTimer 取消指定 ID 的定时器,对已触发或已取消的定时器调用是安全的(幂等)。
CancelTimer(id int64)
}
ITimer 定义定时器管理接口,支持一次性定时器和周期性 Ticker 的完整生命周期管理。
type Skeleton ¶
type Skeleton struct {
// contains filtered or unexported fields
}
Skeleton 模块骨架,将 ChanRPC(服务端/客户端)和定时器管理器整合为统一的事件驱动框架。
核心设计思想(Actor 模型): 所有事件(RPC 调用、异步回调、定时器)在单一 goroutine(OnStart)中串行处理, 彻底消除模块内部的并发竞争,开发者无需为访问模块状态加任何锁,极大降低了复杂度。
使用方式:业务模块内嵌 Skeleton,重写 OnInit 注册处理函数,重写 OnDestroy 清理资源, 无需重写 OnStart 和 ChanRPC(Skeleton 已提供默认实现)。
func NewSkeleton ¶
NewSkeleton 创建模块骨架,初始化 ChanRPC 和定时器组件。
各组件缓冲区均为 10000,适合高并发游戏服务器场景下的消息吞吐需求。 若某模块的消息量远超此值,需根据业务峰值流量调整,过小会导致背压和调用方超时。
func (*Skeleton) AsyncCall ¶
AsyncCall 向指定模块发起异步 RPC 调用,结果通过 cb 回调在本模块事件循环中执行。
回调在 OnStart 的 select 循环中消费 ChanAsyncRet 时执行, 与模块其他事件处理串行,无并发问题,可安全访问模块内部状态。
func (*Skeleton) Call ¶
Call 向指定模块发起同步 RPC 调用,阻塞当前模块的事件处理直到收到响应。
危险提示:Call 会阻塞本模块对其他消息的处理; 若 A 调用 B,同时 B 也在等待 A 的响应,则形成死锁,需通过仔细的调用关系分析来规避。 在事件循环中应优先使用 AsyncCall,仅在调用关系明确单向且不存在环路时才使用 Call。
func (*Skeleton) CancelTimer ¶
CancelTimer 取消指定 ID 的定时器,同时清理业务层元数据,对已触发/已取消的定时器调用安全(幂等)。
func (*Skeleton) DelayTimer ¶
DelayTimer 按指定方式延迟定时器,推迟其触发时间。
func (*Skeleton) NewTicker ¶
NewTicker 创建周期性定时器,每隔 duraMs 毫秒触发一次,触发后自动续期直到被取消。
id 为 0 时自动生成新 ID;传入已有 ID 时复用该定时器(覆盖更新周期), 可用于动态调整已有 Ticker 的触发频率,无需先取消再重建。
func (*Skeleton) OnStart ¶
OnStart 启动模块事件循环,阻塞至 ctx 被取消(即框架调用 cancel)。
事件循环采用 select 多路复用以下三类事件,保证在单一 goroutine 内串行处理:
- ctx.Done():接收框架的停止信号,触发模块关闭流程
- ChanAsyncRet:处理本模块发起的异步 RPC 调用的返回结果(执行注册的 Callback)
- ChanCall:处理其他模块发来的 RPC 调用请求(查找并执行已注册的 Handler)
- ChanTimer:处理到期的定时器事件(执行注册的 TimerHandler,并自动续期 Ticker)
单 goroutine 串行处理是性能与正确性权衡的结果: 牺牲了 CPU 并行利用率,换取了零锁开销和极低的编程复杂度。
func (*Skeleton) RegisterChanRPC ¶
RegisterChanRPC 注册 RPC 消息处理函数,通过 msg 的类型自动推导消息 ID 并完成路由注册。
通常在 OnInit 中批量注册,注册完成后路由表不再变更,访问无需加锁。
func (*Skeleton) RegisterTimer ¶
func (s *Skeleton) RegisterTimer(kind string, handler timermgr.TimerHandler)
RegisterTimer 注册指定 kind 类型的定时器处理函数,通常在 OnInit 中调用完成所有注册。