创建与生命周期
Actor 的创建方式、生命周期状态与系统消息(含 Prelaunch、OnLaunch/OnKill/OnKilled)、发起终止
本文说明 Actor 的创建方式、生命周期与发起终止:如何创建根/子 Actor、生命周期中的预启动与系统消息、如何发起终止。Watch/Unwatch、主动上报故障、僵尸状态、ActorRef 与从字符串解析、组合多个 Actor 见各专题。实现方式见 实现 Actor,创建时选项见 Actor 配置。
创建与层级
系统级创建(根 Actor)
在程序入口通常只创建一个 ActorSystem,再在系统上创建根 Actor:
system := bootstrap.NewActorSystem()
// ...
ref, err := system.ActorOf(&MyActor{}, vivid.WithActorName("root"))system.ActorOf(actor, options...)为并发安全,可在多 goroutine 中调用。- 返回的 ActorRef 用于后续 Tell/Ask、传给其他 Actor 或查找。
在上下文中创建子 Actor
在某个 Actor 的 OnReceive 内,通过 ActorContext 创建子 Actor:
childRef, err := ctx.ActorOf(&WorkerActor{}, vivid.WithActorName("worker-1"))- 子 Actor 的父级为当前
ctx.Ref(),生命周期由当前 Actor 管理。 - 父级会自动 Watch 子级,子级终止时父级会收到
*vivid.OnKilled,无需手动 Watch;该监听由父子关系绑定,父 Actor 无法对子 Actor 调用 Unwatch 取消。主动监听非子级 Actor 的终止见 Watch 与 Unwatch。 - 同一父级下子 Actor 名称必须唯一;不指定名称时系统会自动分配。
- 创建成功后,子 Actor 会经历预启动(Prelaunch)(若实现),再收到
*vivid.OnLaunch,然后开始接收业务消息。ctx.Children()返回当前已创建的子 Actor 引用列表(快照),可用于批量 Tell、监控或监督逻辑。
并发限制
ctx.ActorOf 非并发安全。不要在多个 goroutine 中并发创建同一父级下的子 Actor,应在单次消息处理内或串行逻辑中创建。
命名与配置
- WithActorName(name):指定名称,同父下唯一;不传则系统自动生成。
- 其他创建时选项(邮箱、默认 Ask 超时、Logger、监督策略、Provider 等)见 Actor 配置。
创建失败与错误
ActorOf 可能返回 ErrorActorAlreadyExists(同父下名称重复)、ErrorActorSpawnFailed(创建或预启动失败)、ErrorActorDeaded(在已死亡的父级上创建)等。可用 errors.Is(err, vivid.ErrorActorAlreadyExists) 等方式判定。错误体系见 错误。
生命周期概览
单个 Actor 的状态流转:
父子与终止、OnKilled:父创建子后,子经历上述生命周期;子被 Kill 或故障终止后,父级会收到 OnKilled(Ref 为该子)。父自身终止时也会在流程中收到 Ref 为自己的 OnKilled。
在 OnReceive 中可通过类型断言区分系统消息与业务消息:
| 消息类型 | 含义 |
|---|---|
*vivid.OnLaunch | 启动后收到的第一条业务前消息,用于初始化 |
*vivid.OnKill | 收到终止请求,可做优雅收尾 |
*vivid.OnKilled | 某 Actor 已终止的通知(Ref 为被终止的 Actor),用于清理或通知 |
Prelaunch 与 OnLaunch 的区别
| 维度 | Prelaunch(OnPrelaunch) | OnLaunch |
|---|---|---|
| 时机 | 在 Actor 正式“启动”之前,尚未开始接收消息 | 启动后收到的第一条消息,已具备完整邮箱与上下文 |
| 上下文 | 仅 PrelaunchContext(Logger、Ref),不能 Tell/ActorOf/Watch | ActorContext 完整可用,可发消息、创建子 Actor、订阅等 |
| 典型场景 | 配置校验、环境检查、依赖注入、预加载只读数据;任一失败可令启动中止(返回 error) | 向注册中心注册、订阅 EventStream、创建子 Actor、发起首次 Tell/调度;需要与系统其它部分交互的“上线”逻辑 |
| 失败后果 | 返回 error → Actor 不启动,ActorOf 返回错误 | 若在此 panic 或 Failed,由父级监督策略处理(如重启) |
简单划分:仅做校验与准备、且不需发消息或创建子 Actor 时用 Prelaunch;需要与系统其它 Actor 或组件交互的“上线”逻辑放在 OnLaunch。
启动阶段
Prelaunch
在首次创建与启动时,若 Actor 实现了 PrelaunchActor,系统会在投递 OnLaunch 之前先调用 OnPrelaunch,用于依赖注入、配置校验、资源预加载等。该阶段在生命周期图中对应「预启动」。
| 接口 | 方法 | 调用时机 |
|---|---|---|
| PrelaunchActor | OnPrelaunch(ctx PrelaunchContext) error | 正式启动前(在 OnLaunch 之前);返回 error 则启动失败 |
PrelaunchContext 提供 Logger()、Ref();不提供消息发送、子 Actor 创建等运行时能力。不定义新类型时可用 vivid.NewPrelaunchActor(prelaunchFn, actor) 挂载预启动逻辑;未传入的 actor 使用占位空实现。
运行阶段
OnLaunch
Actor 通过预启动(若有)并完成创建后,收到的第一条系统消息。此时已有完整 ActorContext(可 Tell/Ask、ActorOf、Watch、EventStream、Scheduler 等),适合做需要运行时上下文的操作:向外部或本系统其它 Actor 注册自己、订阅事件流、创建子 Actor、调度首次任务等。
OnKill
收到 *vivid.OnKill 时,可读取以下字段并做收尾:
| 字段 | 说明 |
|---|---|
| Killer | 发起终止请求的 ActorRef |
| Reason | 终止原因描述,便于日志记录与问题定位 |
| Poison | false 为立即终止(OnKill 作为系统消息投递,不处理剩余用户消息队列);true 为毒丸模式(OnKill 作为用户消息入队,处理完当前与队列中的用户消息后再处理 OnKill 并终止) |
收到 OnKill 时,终止已经注定开始,msg.Poison 仅表示本次是以何种方式被请求终止(立即或毒丸),用于日志或收尾策略参考;无法通过代码改变终止方式,只能根据字段做相应清理或记录。
示例:
case *vivid.OnKill:
// 根据 Poison / Reason 决定收尾粒度或打日志;终止流程由框架继续
if msg.Poison { /* 本次为毒丸模式 */ } else { /* 本次为立即终止 */ }OnKilled
*vivid.OnKilled 表示“某 Actor 已终止”,当前 Actor 会在以下情况收到:
- 自己:终止流程中会收到一条 Ref 为自己的 OnKilled。
- 子 Actor:父级自动监听子级,子级终止时父级收到,Ref 为该子 Actor。
- 通过 Watch 监听的 Actor:被监听者终止时收到,Ref 为被监听的 Actor。
消息中的 Ref 为被终止的 Actor 引用,可根据 Ref 判断是谁终止,并做清理、重新创建或告警。主动监听非子级 Actor 见 Watch 与 Unwatch。
发起终止(Kill)
向指定 ActorRef 发送终止请求:框架会向该 Actor 投递 *vivid.OnKill,目标可在 OnReceive 中处理并做优雅收尾。
ctx.Kill(targetRef, poison, "reason")
// 或
system.Kill(targetRef, poison, "reason")- poison:
false立即终止(不处理剩余队列);true毒丸模式(处理完当前与队列中的消息后再终止)。 - reason:可变参数,会拼接为字符串写入 OnKill.Reason。
- 终止请求异步,调用后立即返回;目标终止后会向所有 Watch 该 ref 的 Actor 发送 OnKilled。监听其他 Actor 终止见 Watch 与 Unwatch。
相关专题
- Actor 引用:引用概念与 ParseRef / FindActor / CreateRef。
- 监视(Watch / Unwatch):监听任意 Actor 的终止事件。
- 监督策略:主动上报故障(Failed)、重启失败与僵尸状态、决策与重启阶段钩子。
- 组合多个 Actor:将多个逻辑 Actor 合并为一个对外 Actor。