使用路由器时获取演员的参考

Get reference of an actor when using a router

我正在尝试处理可以 "sessionized" 进入会话的事件流。计划是使用一个演员池,池中的一个演员将处理一个会话中的所有事件(原因是我需要维护一些会话状态)。在我看来,为了实现这一点,我必须为分配给特定会话的特定演员保留 ActorRef。但是,如果我通过以下方式使用演员池:

val randomActor = _system.actorOf(Props[SessionProcessorActor].withRouter(RandomPool(100)), name = "RandomPoolActor")

然后,在这种情况下,randomActor 向整个池提供 ActorRef,而不是池中的单个 actor。我怎样才能达到我上面提到的目标?

我能想到的一种方法是在池中的 actor 初始化后发回引用(可能类似于 RandomPoolActor$ab 等)。然而,这种方法有一些问题,其中之一是我必须使用询问模式而不是告诉,这样我就不会错过同一会话中的事件。

还有其他方法可以实现吗?还有其他模式要采用吗?

您可以使用 ConsistentHashingPool 来执行与您正在寻找的内容类似的操作。 ConsistentHashingRouter 确保每条消息都在基于 hashKey 的同一个参与者中结束。在您的场景中,此密钥将是您的 sessionId。无需保留 ActorRefs 或其他引用即可完成此操作。

有多种方法可以在代码中定义 hashKey。我建议创建一个扩展 ConsistentHashable 的案例 class。完成后,您将需要实施方法 consistentHashKey。示例:

case class HashableEnvelope(yourMsgClass: YourMsgClass) extends ConsistentHashable {
  override def consistentHashKey = yourMsgClass.sessionId
}

然后你可以这样定义你的池:

val pool = system.actorOf(Props[SessionProcessorActor].withRouter(ConsistentHashingPool(100)))

另一件需要提及的事情是,路由器将确保具有相同 hashKey 的所有消息都将在同一个 actor 中结束,但是,它不能确保特定 actor 仅接收给定 hashKey 的消息。它可以接收多个 hashKeys。这应该不是问题,只是你的 SessionProcessorActor 应该能够处理几个 hashKey 而不是一个。

一致性哈希算法将决定将哪个消息发送给每个参与者。您可以在维基百科上阅读它是如何工作的:https://en.wikipedia.org/wiki/Consistent_hashing。要以更均匀的方式分发消息,您应该增加配置中的虚拟节点数(默认为 10):

akka.actor.deployment.default.virtual-nodes-factor = 1000

根据您拥有的 sessionId 和参与者的数量,您会看到消息分布得更均匀。