【问题标题】:Dead letters encountered in Akka when routing between sibling Actors在兄弟 Actor 之间路由时在 Akka 中遇到死信
【发布时间】:2019-06-09 20:48:25
【问题描述】:

我正在尝试构建一个基于代理的模型,其中模型的一部分涉及代理广播决策。首先,我用一个跟踪父级精确地初始化了四个演员,然后我让他们每个人都以特定的顺序“宣布”他们的决定。

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

主要方法:

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()
  }

【问题讨论】:

  • 你可以在这里粘贴死信日志行吗?

标签: scala akka agent-based-modeling


【解决方案1】:

通过查看您的代码,很明显参与者消息将被传递到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()被调用时,handleractor被停止,然后testeractor被停止。然而,在testeractor 停止之前,仍然可以有"START" 消息被发送到handleractor。但是,handler 演员已经停止,这个"START" 消息将不再传递给handler,因此传递给deadletters

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

如何确保所有参与者按顺序运行,接收所有声明 来自兄弟姐妹,直到他们收到一条消息才终止 声明自己?

为此,您可以将PoisonPill 消息显式传递给每个参与者,这将仅在其邮箱中的所有消息都被处理后才会停止参与者。

【讨论】:

    猜你喜欢
    • 2019-04-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-26
    • 1970-01-01
    相关资源
    最近更新 更多