在同级Actor之间路由时在Akka中遇到死信

时间:2019-06-09 20:48:25

标签: scala akka agent-based-modeling

我正在尝试构建基于代理的模型,其中部分模型涉及代理广播决策。首先,我会使用跟踪父对象准确地初始化四个参与者,然后让他们每个人以特定顺序“宣告”他们的决定。

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

主要方法:

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

1 个答案:

答案 0 :(得分:1)

通过查看您的代码,很明显参与者消息将传递到deadletters。在您的代码中,您正在try-catch-finally语句的system.terminate()块中调用finally,这意味着actor系统终止将在try块之后立即发生,这将立即停止所有演员。但是,您应该知道 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停止之前,仍然可能有"START"消息被发送到handler actor。但是,handler actor已经停止,此"START"消息将不再传递给handler,因此也传递给deadletters

因此,在您的代码中,执行system.terminate()后,所有参与者-groupfathermotherwifehusband会立即停止,因此发送到这些actor邮箱的所有其他消息都会传递给合成actor deadletters

  

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

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