在兄弟 Actors 之间路由时在 Akka 中遇到死信

Dead letters encountered in Akka when routing between sibling Actors

我正在尝试构建一个基于代理的模型,该模型的一部分涉及代理广播决策。首先,我用跟踪 parent 初始化四个演员,然后我让他们每个 "declare" 以特定顺序做出决定。

我希望每个兄弟姐妹每次都宣布其决定时更新其参数,但是当我 运行 下面显示的代码时,我会收到有关遇到死信的日志。我如何确保所有演员 运行 按顺序接收兄弟姐妹的所有声明并且在他们收到声明自己的消息之前不终止?

主要方法:

import Member._

  val system: ActorSystem = ActorSystem("Abilene0")

  try {
    val groupMembers = Set("father", "mother", "wife", "husband")
    val group: ActorRef = system.actorOf(Group.props(groupMembers), "group")

    val father = system.actorOf(Member.props(group, generate(groupMembers)), "father")
    val mother = system.actorOf(Member.props(group, generate(groupMembers)), "mother")
    val wife = system.actorOf(Member.props(group, generate(groupMembers)), "wife")
    val husband = system.actorOf(Member.props(group, generate(groupMembers)), "husband")

    father ! Declare
    wife ! Declare
    husband ! Declare
    mother ! Declare

  } finally {
    system.terminate()
  }

通过查看您的代码,很明显演员消息将传送到 deadletters。在您的代码中,您在 try-catch-finally 语句的 finally 块中调用 system.terminate(),这意味着,actor 系统终止将在您的 try-block 之后立即停止所有的演员。但是,您应该知道 Actor 使用异步消息进行通信。这意味着,即使在您的 try-block 代码完成后,您的 actor 中仍可能会执行各种后台任务,直到所有 actor 都停止。

让我为您创建一个场景:

class Handler extends Actor with ActorLogging{
  override def receive: Receive = {
    case "START" =>
      println("Test Started.")
  }
}

class Tester(handler: ActorRef) extends Actor with ActorLogging{
  override def receive: Receive = {
    case "TEST" =>
      println("Test started.")
      // Here, when handler actor stops when system.terminate() occur, "START" message
      // will be no longer delivered to actor handler instead delivered to deadletters.
      1 to 1000 foreach ( _ => {
        handler ! "START"
      })
  }
}

val system: ActorSystem = ActorSystem("test")
val handler = system.actorOf(Props(new Handler), "handler")
val tester = system.actorOf(Props(new Tester(handler)), "tester")
try {
  tester ! "TEST"
} finally {
  system.terminate()
}

在上面的代码中,当调用 system.terminate() 时,handler actor 停止,然后 tester actor 停止。但是,在 tester actor 停止之前,仍然可以向 handler actor 发送 "START" 消息。但是,handler actor 已经停止,此 "START" 消息将不再传递给 handler,因此传递给 deadletters

因此,在您的代码中,在执行 system.terminate() 后,您的所有演员 - groupfathermotherwifehusband 立即停止,因此发送到这些演员邮箱的任何进一步消息都将传递给合成演员 deadletters

How do I make sure all actors run in order, receive all declarations from siblings and do not terminate until they receive a message to declare themselves?

为此,您可以将 PoisonPill 消息显式传递给每个 actor,这将仅在处理完其邮箱中的所有消息后停止 actor。