Vivid
集群

集群单例

集群内唯一 Actor、WithClusterSingleton、SingletonRef

集群单例(Cluster Singleton)保证全集群仅有一个实例,且该实例运行在当前 Leader 节点上。Leader 或 Quorum 变化时,框架会在新 Leader 上创建单例、在旧节点上销毁,语义与 Akka Cluster Singleton 对齐。

注册单例模板

在配置集群时通过 WithClusterSingleton(集群可选项)注册单例模板(名称 + ActorProvider):

system, err := bootstrap.NewActorSystem(
    vivid.WithActorSystemRemoting("0.0.0.0:8080", "node1:8080"),
    vivid.WithActorSystemRemotingClusterOption(
        vivid.WithClusterSeeds([]string{"seed:8080"}),
        vivid.WithClusterSingleton("my-singleton", vivid.ActorProviderFN(func() vivid.Actor {
            return &MySingletonActor{}
        })),
    ),
)
参数说明
name单例逻辑名,用于 SingletonRef(name) 查找。
provider在 Leader 节点上创建单例实例的 ActorProvider;每次迁移到新 Leader 时都会创建新实例。

仅当启用集群且至少注册一个单例模板时,框架会管理单例的创建与迁移。

获取单例引用

通过 ClusterContext.SingletonRef(name) 获取该单例的 ActorRef(本地代理):

  • Leader 变更时自动更新转发目标,单例迁移后无需重新获取 ref
  • 无可用单例时,消息会缓存在代理中,待单例就绪后转发。
cluster := ctx.Cluster()
if cluster == nil {
    return
}
ref, err := cluster.SingletonRef("my-singleton")
if err != nil {
    // ErrorClusterDisabled、ErrorNotFound(未注册该 name)、ErrorIllegalArgument 等
    return
}
ctx.Tell(ref, msg)  // 代理会转发到当前 Leader 上的单例
  • 单例侧通过 ctx.Sender() 看到的是原始调用方;代理与单例可在不同节点,转发时发送方与业务消息由框架按内部格式序列化并在单例侧还原,无需业务配置。
  • 因使用本地代理,单例迁移后 ref 仍然有效,消息不会因 Leader 切换而丢失或发往旧节点。
  • 发往单例的业务消息需满足 Remoting 的序列化要求(Codec 或 RegisterCustomMessage),以便跨节点转发时正确编解码。

行为说明

  • 单例仅运行在当前 Leader 且 InQuorum 的节点上;Leader 切换时自动在新 Leader 上创建、在旧节点上销毁。
  • SingletonRef 返回的为本地代理 ref,随 Leader 变更自动转发,无需在业务侧重新获取或订阅事件。

错误码

错误说明
ErrorClusterDisabled未启用集群或集群未就绪时调用。
ErrorNotFound未注册该 name 的模板。
ErrorIllegalArgumentname 为空。

On this page