如何处理发送给被钝化的演员的消息

时间:2018-07-07 20:34:34

标签: scala akka akka-persistence

我必须创建一组持久性参与者,并通过一些ID将消息路由给他们。 当我这样做时,我会在路由器演员中使用类似以下的命令查找目标对象:

context.child(id) getOrElse create(id) - creating actors by context.actorOf()

,并且路由器找到子节点之后,它将转发消息(否则首先创建子节点)。

为了节省空间,我还通过调用子actor来对子actor使用某种自定义钝化-setReceiveTimeout => ReceiveTimeout =>发送要钝化的actor自定义Shutdown消息,它在收到context.stop(self)后会被调用。

如果实际的actor关闭发生在父actor已将ActorRef发送给已经停止的孩子之后但在转发消息之前发生了呢?消息会丢失吗?

我认为此问题可以通过保存传入的消息并在actor重新激活时重放它们来通过akka分片(可能是ShardRegion)来解决。

问题是由于要求我无法使用Akka分片。 对于钝化参与者的消息处理,是否有现成的解决方案或模式?

谢谢

1 个答案:

答案 0 :(得分:0)

路由器和子actor正在异步运行,因此,当子呼叫context.stop(self)时,邮箱中仍有待处理的消息。在这种情况下,这些消息将丢失(路由到死信)

为避免消息丢失,孩子不能自行关闭,而需要与路由器协调。例如:

  1. 孩子:setReceiveTimeout
  2. 孩子:在收到ReceiveTimeout后,向路由器发送一条自定义Stopping消息
  3. 路由器:在接收到Stopping时,停止将消息路由到孩子,并将自定义的Stop消息(或PoisonPill)发送给孩子
  4. 孩子:收到Stop后,致电context.stop(self)

在第3步中,路由器可能需要维护自己的子代地图,而不是依靠context.child

在第4步中,由于保证了两个参与者之间的消息顺序,因此Stop消息将始终是来自路由器的最后一条消息,因此可以安全地停止。