为什么 Receptionist.Subscribe Akka 中的第一条消息不包含使用指定密钥注册的所有集群成员?

Why Receptionist.Subscribe first messages in Akka don't contain all cluster members registered with the specified key?

我有两个参与者:第一个已经在集群中(全部在本地主机中)端口 25457,第二个将在端口 25458 启动。

两者都有以下行为:


    val addressBookKey = ServiceKey[Message]("address_book")
    val listingResponseAdapter = ctx.messageAdapter[Receptionist.Listing] { 
    case addressBookKey.Listing(p) => OnlinePlayers(p) }
    
    Cluster(ctx.system).manager ! Join(address)
    ctx.system.receptionist ! Register(addressBookKey, ctx.self)
    ctx.system.receptionist ! Subscribe(addressBookKey, listingResponseAdapter)
    
    Behaviors.receiveMessagePartial { 
      case m =>
        System.err.println(m)
        Behaviors.same
    }

当第二个演员加入 stderr 打印 Set()Set(Actor[akka://system/user#0]) 然后 Set(Actor[akka://system/user#0], Actor[akka://system@localhost:27457/user#0])

当第二个演员离开时,第一个演员打印两次Set(Actor[akka://system/user#0])

第二个actor如何直接接收所有集群参与者?
为什么第一个演员在第二个演员离开后打印了两倍的布景?

谢谢

加入集群是一个异步过程,您只是通过向管理器发送 Join 来触发加入,实际上加入集群是在之后的某个时间点发生的。接待员只能知道已完成加入集群的节点上的注册服务。

这意味着当你订阅 receptionist 时,加入集群可能还没有完成,所以你得到本地注册的服务(因为排序保证 receptionist 在收到订阅之前总是会得到本地注册消息), 然后一旦加入集群完成,接待员就会了解其他节点上的服务并更新订阅者。

为了确保其他节点已知,您必须等待订阅,直到节点加入集群,这可以通过订阅集群状态并仅在节点本身被标记为 Up.

一般来说,无论是否加入集群节点,制作都能正常工作的东西通常是好的,因为它使测试更容易,而且 运行 没有集群的相同组件。因此,例如,当没有注册服务与至少一个服务或服务密钥的服务数量最少时订阅参与者的切换行为。

不完全确定当另一个节点上的参与者“离开”时为什么会看到重复的更新,但是关于用于接待员注册表的 CRDT 有一些细节,它可能必须重新删除服务一致性,这也许可以解释它。