使用路由器时获取actor的参考

时间:2016-05-17 18:53:23

标签: akka real-time actor

我正在尝试处理可以“会话”到会话中的事件流。计划是使用一个actor池,其中来自池的单个actor将处理来自一个会话的所有事件(原因是我需要维护一些会话状态)。在我看来,为了让我实现这一点,我必须保持ActorRef周围的特定演员被分配到特定的会话。但是,如果我使用:

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

然后,在这种情况下, randomActor 将ActorRef提供给整个池,而不是池中的各个actor。那我怎么能实现我上面提到的呢?

我能想到的一种方法是在池中的actor初始化之后发回引用(可能看起来像RandomPoolActor $ ab等)。然而,这个方法有一些问题,其中一个是我必须使用ask模式而不是tell,这样我就不会错过来自同一会话的事件。

任何其他方式来实现这一目标?还有其他任何模式吗?

1 个答案:

答案 0 :(得分:2)

您可以使用ConsistentHashingPool来执行与您要查找的内容类似的操作。 ConsistentHashingRouter确保每条消息都基于hashKey在同一个actor中结束。此键将是您的方案中的sessionId。没有必要保持ActorRefs或其他引用来完成此任务。

您可以通过多种方式在代码中定义hashKey。我建议创建一个扩展ConsistentHashable的案例类。完成后,您将需要实施方法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应该能够处理一些hashKeys而不是一个。

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

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

根据您拥有的sessionIds和actor的数量,您将看到该消息的分布更加均匀。