-
Notifications
You must be signed in to change notification settings - Fork 2
kernel
gootp 的核心库,提供类似erlang的supervisor,gen_server功能。
关于进程实现:
Actor
的实现,在第一版是使用interface实现的,后来发现这样没办法热更新,所有后面改为使用全局变量,作为 Actor
的回调模块。
根据benchmark测试,使用全局变量函数会比原生函数的执行多消耗 1ns,如果你特别注重这个性能,尽量少使用,此举完全是为了热更新。
type InitFunc func(ctx *Context,pid *Pid, args ...interface{}) unsafe.Pointer
type HandleCastFunc func(ctx *Context, msg interface{})
type HandleCallFunc func(ctx *Context, request interface{}) interface{}
type TerminateFunc func(ctx *Context, reason *Terminate)
type ErrorHandleFunc func(ctx *Context, err interface{}) bool
type Actor struct {
// 初始化回调
Init InitFunc
// 接收消息
HandleCast HandleCastFunc
// 接收同步调用
HandleCall HandleCallFunc
// actor退出回调
Terminate TerminateFunc
// 当发生catch错误时调用,如果返回false,那么进程将会退出
ErrorHandler ErrorHandleFunc
}
以上是Actor
的数据结构,你只需要实现里面的函数,就可以调用kernel.Start
启动一个进程服务。
主要api列表:
[kernel]
-
KernelStart(start func(),stop func())
核心函数,所有自有逻辑都必须在
start
函数中实现,框架启动完成后,会执行start()
。如果你有一些逻辑需要优先关闭,你可以传入stop
函数。!!!如果你使用了gootp/gate 库,请务必传入一个stop函数,如:
func stopGame(){ gate.Stop() }
如需停止服务,调用kernel.InitStop()
或者通过网页请求:curl "http://127.0.0.1:3000/stop"
框架会根据服务启动的顺序,倒序关闭服务,最后退出。
[gen_server]
-
Start(newActor *Actor, args ...interface{}) (*Pid, interface{})
启动一个匿名进程。 -
StartName(name string, newActor *Actor, args ...interface{}) (*Pid, interface{})
启动一个带名字的进程。 -
Cast(pid *Pid, msg interface{})
向一个进程发生一个cast消息,你可以在HandleCast
回调中处理。 -
CastName(name string, msg interface{})
-
CastNameNode(name string, node interface{}, msg interface{})
向一个分布式节点发送cast消息。 -
Call(pid *Pid, request interface{}) (bool, interface{})
向一个进程发起同步调用,你可以在HandleCall
回调中处理。 -
CallName(name string, request interface{}) (bool, interface{})
-
CallNameNode(name string, node interface{}, request interface{}) (bool, interface{})
向一个分布式节点的进程发起同步请求。 -
CallTimeOut(pid *Pid, request interface{}, timeOut time.Duration) (bool, interface{})
向一个进程发起同步调用,可以指定超时时间(秒)。
[Context]
也有一批类似的api
-
(c *Context) CastName(name string, msg interface{})
-
(c *Context) CastNameNode(name string, node interface{}, msg interface{})
-
(c *Context) Cast(pid *Pid, msg interface{})
-
(c *Context) CallName(name string, request interface{}) (bool, interface{})
-
(c *Context) Call(pid *Pid, request interface{}) (bool, interface{})
-
(c *Context) CallNameNode(name string, node interface{}, request interface{}) (bool, interface{})
-
(c *Context) StartLink(newActor *Actor, args ...interface{}) (*Pid, interface{})
-
(c *Context) StartNameLink(name string, newActor *Actor, args ...interface{}) (*Pid, interface{})
更多可以自行查阅
[supervisor]
-
SupStart(name string, initChild []*SupChild) *Pid
启动一个监控进程,如果传入了initChild
,那么 child 也会被启动。 -
SupStop(sup interface{})
关闭一个监控进程,同时他的 child 也会被关闭。 -
SupStartChild(sup interface{}, child *SupChild) (interface{}, *Pid)
启动一个 child 进程,并且把进程挂载在监控进程下面。 -
SupWhichChild(sup interface{}) []*SupChildInfo
获取监控进程下的所有子进程。
gootp/kernel/time.go 提供了一些基础的时间函数,可以自行查阅。
gootp/kernel/timer.go 提供类似erlang:send_after
的功能。
SendAfter(timerType timerType, pid *Pid, inv int64, msg interface{})
[logger]
框架提供了一个记录logger日志的功能,目前只有2个日志级别。
-
DebugLog(format string, args ...interface{})
-
ErrorLog(format string, args ...interface{})
你只需要配置一个环节变量:
kernel.Env.WriteLogStd = true // 是否输出到控制台
kernel.Env.LogPath = "../logs" // 如果不填,默认输出到 `./log` ,也可以填 "",表示不记录到文件
kernel.KernelStart(initGame,stopGame)
如果你不喜欢使用这个日志库,你可以在kernel.KernelStart(initGame,stopGame)
启动前,调用:
-
kernel.TouchLogger(writer io.Writer)
接管所有的日志消息,你不需要担心线程安全问题,因为上层是单线程执行的。
kernel
提供了一个特殊数据结构 kernel.KMsg
该数据结构可以直接发往分布式节点上,前提是你注册了KMsg.Msg
到node
中。
更多api你可以通过Goland查阅。