首页 > 解决方案 > 如何处理发送给被钝化的演员的消息

问题描述

我必须创建一组持久性参与者并通过一些 id 将消息路由给他们。当我这样做时,在我的路由器演员中,我使用以下内容查找目标​​:

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

在路由器找到孩子之后,它会转发消息(否则首先创建孩子)。

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

如果实际的actor关闭发生在父actor获取ActorRef到已经在停止中的子actor之后,但在它转发消息之前呢?消息会丢失吗?

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

问题是由于我不能使用 Akka Sharding 的要求。是否有现成的解决方案或模式来处理钝化参与者的消息问题?

谢谢

标签: scalaakkaakka-persistence

解决方案


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

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

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

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

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


推荐阅读