Акка широковещательный запрос не доставляет на все маршруты - PullRequest
0 голосов
/ 17 октября 2018

Я учусь использовать широковещательные сообщения в маршрутизаторах Akka.Есть ли способ получить ответы на ask со всех маршрутов к роутеру?

У меня есть этот пример кода.

Master.scala

object Master {
    case object brdcst
}

class Master extends Actor {
    implicit val timeout = Timeout(5 seconds)

    val router: ActorRef = context.actorOf (RoundRobinPool (3).props(Props[Worker]), "router")

    override def receive: Receive = {
        case brdcst => {
            val future = router ? Broadcast(brdcst)
            val result = Await.result(future, timeout.duration)
            println("result = " + result)
        }
    }
}

object MasterTest extends App {
    val actorSystem = ActorSystem("ActorSystem")
    val actor = actorSystem.actorOf(Props[master], "root")
    actor ! brdcst
}

Worker.scala

class Worker extends Actor {
    val routee = context.actorOf(Props[Worker], "routee")

    override def receive: Receive = {
        case brdcst => sender() ! self.path.name
    }
}

Этот код дает следующий вывод

result = $a
[INFO] [10/16/2018 21:47:07.484] [ActorSystem-akka.actor.default-dispatcher-2] [akka://ActorSystem/deadLetters] Message [java.lang.String] from Actor[akka://ActorSystem/user/root/router/$a#340358688] to Actor[akka://ActorSystem/deadLetters] was not delivered. [1] dead letters encountered. If this is not an expected behavior, then [Actor[akka://ActorSystem/deadLetters]] may have terminated unexpectedly, This logging can be turned off or adjusted with configuration settings 'akka.log-dead-letters' and 'akka.log-dead-letters-during-shutdown'.
[INFO] [10/16/2018 21:47:07.504] [ActorSystem-akka.actor.default-dispatcher-10] [akka://ActorSystem/deadLetters] Message [java.lang.String] from Actor[akka://ActorSystem/user/root/router/$b#-151225340] to Actor[akka://ActorSystem/deadLetters] was not delivered. [2] dead letters encountered. If this is not an expected behavior, then [Actor[akka://ActorSystem/deadLetters]] may have terminated unexpectedly, This logging can be turned off or adjusted with configuration settings 'akka.log-dead-letters' and 'akka.log-dead-letters-during-shutdown'.

Таким образом, ответ приходит только от одного пользователя.Как получить ответы от всех маршрутов?(Может быть, как список, как result = [$a, $b, $c])

1 Ответ

0 голосов
/ 17 октября 2018

ask (?) создает внутреннего субъекта для обработки ответов.Этот внутренний субъект обрабатывает только один ответ и автоматически отключается: по этой причине вы получаете только первый ответ, в то время как ответы от двух других маршрутов переходят в пустые буквы.

Чтобы получить желаемое поведение,используйте tell (!) и собирайте ответы от маршрутов.Например:

class Master extends Actor {
  val numRoutees = 3
  val router = context.actorOf(RoundRobinPool(numRoutees).props(Props[Worker]), "router")

  def handleMessages(replies: Set[String] = Set()): Receive = {
    case brdcst =>
      router ! Broadcast(brdcst)
    case reply: String =>
      val updatedReplies = replies + reply
      if (updatedReplies.size == numRoutees) {
        println("result = " + updatedReplies.mkString("[", ",", "]"))
      }
      become(handleMessages(updatedReplies))
  }

  def receive = handleMessages
}

В приведенном выше примере мастер кодирует ответы маршрутов как часть своего состояния, используя become.

Кроме того, donНе используйте Await в актерах.

...