Почему Акка висит, порождая детского актера - PullRequest
0 голосов
/ 28 января 2020

Я пытаюсь реализовать механизм A / B-тестирования с использованием актеров Akka (scala 2.12.8, akka-actor-typed 2.6.1)

Я разработал его как:

  • 1 A / B Testing root actor
  • 2 Вариант актеров, потомки A / B Testing actor

Когда актер A / B Testing получит сообщение, он выберет один вариант и переслать сообщение ему.

Однако до сих пор мне не удавалось заставить актера root порождать его детей. Вот мой код.

import akka.actor.typed.{ActorRef, ActorSystem, Behavior}
import akka.actor.typed.scaladsl.{AbstractBehavior, ActorContext, Behaviors}

import scala.util.Random

// My variants
object Ranker {
  sealed trait Command
  final case class Rank() extends Command
  def apply(rank: Int): Behavior[Command] = Behaviors.setup { context => new Ranker(context, rank) }
}

class Ranker(context: ActorContext[Ranker.Command], rank: Int) extends AbstractBehavior[Ranker.Command](context) {
  override def onMessage(msg: Ranker.Command): Behavior[Ranker.Command] = {
    println(rank)
    this
  }
}

// The root A/B Testing actor
object ABTester {
  def apply(): Behavior[Ranker.Command] = Behaviors.setup { context => new ABTester(context) }
}

class ABTester(context: ActorContext[Ranker.Command]) extends AbstractBehavior[Ranker.Command](context) {
  val rng = new Random()
  // Spawn children actors
  val rankers: Seq[ActorRef[Ranker.Command]] = Seq(Ranker(1), Ranker(2)).zipWithIndex
    .map { case (b, i) =>
      println(s"Spawning ranker $i")
      val actorRef = context.spawn(b, s"Ranker $i")
      println(s"Spawning ranker $i: Done")
      actorRef
    }

  override def onMessage(msg: Ranker.Command): Behavior[Ranker.Command] = {
    rankers(rng.nextInt(rankers.size)) ! msg
    this
  }
}

// Application entry point
object Main {
  def main(args: Array[String]): Unit = {
    val actor = ActorSystem(ABTester(), "ABTester")
    actor ! Ranker.Rank()
    Thread.sleep(5000)
  }
}

При выполнении этого примера будет напечатано:

Spawning ranker 0

, но это все, как если бы строка 31 (val actorRef = context.spawn(b, s"Ranker $i")) никогда не возвращалась ...

Я что-то упустил из-за того, что рождаются детские актеры?

1 Ответ

0 голосов
/ 29 января 2020

TL; DR

Actor paths MUST:
  not start with `$`,
  include only ASCII letters
  and can only contain these special characters: -_.*$+:@&=,!~';.`

Я, наконец, обнаружил ошибку!

Я неправильно настроил запись в журнал, и поэтому сообщение об ошибке никогда не появляется. После добавления зависимости slf4j-simple происходит следующее:

[ABTester-akka.actor.default-dispatcher-3] INFO akka.event.slf4j.Slf4jLogger - Slf4jLogger started
SLF4J: A number (1) of logging calls during the initialization phase have been intercepted and are
SLF4J: now being replayed. These are subject to the filtering rules of the underlying logging system.
SLF4J: See also http://www.slf4j.org/codes.html#replay
[ABTester-akka.actor.default-dispatcher-3] INFO ABTester - Spawning ranker 0
[ABTester-akka.actor.default-dispatcher-3] ERROR akka.actor.LocalActorRefProvider(akka://ABTester) - guardian failed, shutting down system
akka.actor.InvalidActorNameException: Invalid actor path element [Ranker 0], illegal character [ ] at position: 6. Actor paths MUST: not start with `$`, include only ASCII letters and can only contain these special characters: -_.*$+:@&=,!~';.
    at akka.actor.ActorPath$.validatePathElement(ActorPath.scala:98)
    at akka.actor.ActorPath$.validatePathElement(ActorPath.scala:76)
    at akka.actor.dungeon.Children.checkName(Children.scala:248)
    at akka.actor.dungeon.Children.actorOf(Children.scala:47)
    at akka.actor.dungeon.Children.actorOf$(Children.scala:46)
    at akka.actor.ActorCell.actorOf(ActorCell.scala:408)
    at akka.actor.typed.internal.adapter.ActorRefFactoryAdapter$.spawn(ActorRefFactoryAdapter.scala:41)
    at akka.actor.typed.internal.adapter.ActorContextAdapter.spawn(ActorContextAdapter.scala:66)
    at ABTester.$anonfun$rankers$1(ABTester.scala:31)
    [...]

Путь к действующему субъекту (переданный методу spawn) не должен содержать пробелов.

Изменение с Ranker $i до Ranker_$i результат:

[ABTester-akka.actor.default-dispatcher-3] INFO akka.event.slf4j.Slf4jLogger - Slf4jLogger started
[ABTester-akka.actor.default-dispatcher-6] INFO ABTester - Spawning ranker 0
[ABTester-akka.actor.default-dispatcher-6] INFO ABTester - Spawning ranker 0: Done
[ABTester-akka.actor.default-dispatcher-6] INFO ABTester - Spawning ranker 1
[ABTester-akka.actor.default-dispatcher-6] INFO ABTester - Spawning ranker 1: Done
[ABTester-akka.actor.default-dispatcher-3] INFO Ranker - rank: 2
...