Актер срабатывает случайным образом

Я использую AKKA Actors (версия 2.3.9) с использованием Scala API.

У меня есть куча разнородных Актеров, которые должны срабатывать каждые 30 минут. Я вижу, что за один прогон не все актеры срабатывают. Это совершенно случайно. Каждый актер не выполняет, так сказать, никаких тяжелых задач. Они совершают много операций чтения в хранилище NoSQL и несколько операций записи. Не уверен, в чем здесь настоящая проблема. Я чувствую, что где-то я не использую идеальный подход.

Это код:

 val system = ActorSystem("pumpkinx-akka")
import system.dispatcher
val noOfActors = 50
val allActors = List(
      system.actorOf(Props[a.actors.TriggerActor].withRouter(new RoundRobinRouter(noOfActors)), "aTriggerActor"),
      system.actorOf(Props[b.actors.TriggerActor].withRouter(new RoundRobinRouter(noOfActors)), "bTriggerActor"),
      system.actorOf(Props[c.actors.TriggerActor].withRouter(new RoundRobinRouter(noOfActors)), "cTriggerActor"),
      system.actorOf(Props[d.actors.TriggerActor].withRouter(new RoundRobinRouter(noOfActors)), "dTriggerActor"),
      system.actorOf(Props[e.actors.TriggerActor].withRouter(new RoundRobinRouter(noOfActors)), "eTriggerActor"))
def trigger = allActors.foreach(_ ! new Start)
system.scheduler.schedule(0 seconds, 30 minutes)(trigger)
system.awaitTermination()

person user1189332    schedule 16.04.2015    source источник
comment
Не уверен, что именно вы ожидали, вы определили RoundRobinRouter, и это означает, что не все из них получают сообщение.   -  person sap1ens    schedule 16.04.2015
comment
Я ожидаю: за один прогон я смогу отправить сообщение «Пуск» всем участникам a, b, c, d, e — не обязательно всем 50. По крайней мере, один актер «А» был бы в порядке. Проблема, которую я вижу, заключается в том, что актер «e» иногда вообще не срабатывает. Точно так же «b» иногда вообще не срабатывает. Это совершенно случайно и трудно наблюдать закономерность.   -  person user1189332    schedule 16.04.2015


Ответы (1)


Вы создали 5 маршрутизаторов с 50 акторами в каждом, так что это 250 *.actors.TriggerActor. Если вы хотите отправить сообщение всем 250 за один раз, вам следует:

 def trigger = (1 to 50).foreach(_ => allActors.foreach(_ ! new Start))

Он отправит 50 сообщений на каждый маршрутизатор. Поскольку это круговой алгоритм, первое сообщение, пришедшее на маршрутизатор, будет отправлено его первому актору, второе - второму и так далее, пока 50-й актор не получит сообщение.

Просто allActors.foreach(_ ! new Start) отправляет сообщение только одному из 50 акторов - не всем, трансляции нет. Например, a ! Start просто отправляет сообщение одному из экземпляров a.actors.TriggerActor.

P.S. Мое моделирование:

class Trigger extends Actor { 
    def receive = { 
       case x => println(context.parent.path.name + " " + self.path.name + " " + x) 
    }
}
defined class Trigger

val system = ActorSystem("pumpkinx-akka")

val allActors = List(
      system.actorOf(Props[Trigger].withRouter(new RoundRobinRouter(noOfActors)), "aTriggerActor"),
      system.actorOf(Props[Trigger].withRouter(new RoundRobinRouter(noOfActors)), "bTriggerActor"),
      system.actorOf(Props[Trigger].withRouter(new RoundRobinRouter(noOfActors)), "cTriggerActor"),
      system.actorOf(Props[Trigger].withRouter(new RoundRobinRouter(noOfActors)), "dTriggerActor"),
      system.actorOf(Props[Trigger].withRouter(new RoundRobinRouter(noOfActors)), "eTriggerActor"))

scala> allActors.foreach(_ ! "m") //everyone received a message
aTriggerActor $a m
bTriggerActor $a m
cTriggerActor $a m
dTriggerActor $a m
eTriggerActor $a m

scala> (0 to 5).foreach(_ => allActors(1) ! "m") //only to b-router
bTriggerActor $b m //bcdefg (round-robin)
bTriggerActor $g m
bTriggerActor $f m
bTriggerActor $d m
bTriggerActor $e m
bTriggerActor $c m

scala> (0 to 5).foreach(_ => allActors(1) ! "m") //only to b-router
bTriggerActor $h m //hijklm (round-robin)
bTriggerActor $l m
bTriggerActor $j m
bTriggerActor $k m
bTriggerActor $i m
bTriggerActor $m m

P.S. Будьте осторожны с исключениями внутри таких роутеров (точнее внутри воркеров). Если маршрутизатор является субъектом верхнего уровня, сбой будет передан опекуну, что приведет к отключению всей системы.

P.S. Если вам также нужен циклический перебор для разнородных участников, используйте RoundRobinGroup см. примеры

person dk14    schedule 16.04.2015
comment
Насколько я понимаю, каждый из RoundRobinRouter предназначен только для этого конкретного актера. Например: Маршрутизатор 1 будет для 50 акторов «а», Маршрутизатор 2 будет для 50 акторов «б» и так далее. Я хотел бы надежно отправить хотя бы одно сообщение всем актерам «a», «b», «c», «d», «e» за один прогон. Но это не происходит детерминированным образом. Что-то я пропустил? - person user1189332; 16.04.2015
comment
allActors.foreach(_ ! new Start) отправляет сообщение только одному из 50 актеров - не всем, трансляции нет. a ! Start просто отправляет сообщение одному из экземпляров a.actors.TriggerActor - person dk14; 16.04.2015
comment
Хм. Я вижу это. Чего я не понимаю, так это почему ни один актер из «b» не срабатывает в прогоне [Например] - person user1189332; 16.04.2015
comment
Не могли бы вы показать код (актеров) и ввод + вывод (например, println в каждом актере)? - person dk14; 16.04.2015
comment
Я имею в виду, любое моделирование этой ситуации (без system.scheduler.schedule и с тем же типом актора) показывает, что вызываются 5 акторов. - person dk14; 16.04.2015
comment
Большое спасибо, это было очень ясно. Я нашел реальную проблему. Проблема заключается в базовой логике актера. Предложение case в паре акторов имело условие «если», которое зависело от значения, обновляемого в базе данных от другого актора. Следовательно, это было совершенно недетерминировано. В качестве побочного вопроса, могу ли я в любом случае использовать круговой перебор между разнородными актерами? Например: при первом запуске я хочу вызвать «а», при втором запуске «б» и так далее. - person user1189332; 16.04.2015
comment
Да, можете — вам нужно RoundRobinGroup для это. Вы можете прочитать об этом здесь - person dk14; 16.04.2015
comment
Давайте продолжим обсуждение в чате. - person user1189332; 16.04.2015