Последовательность доставки сообщений в актёрах akka - PullRequest
14 голосов
/ 01 июня 2011

Я довольно новичок в Akka и не смог найти ответ в справочном руководстве.

Предположим, что у нас есть удаленные актеры, распределенные в кластере из 3 машин (A, B, C), где один актер живет на каждой машине, а другие имеют actorRef для 2 других, т.е.

Machine A:
A (real actor)
-> B (ref)
-> C (ref)

Machine B:
-> A (ref)
B (real actor)
-> C (ref)

Machine C:
-> A (ref)
-> B (ref)
C (real actor)

Актер А выполняет следующий код:

bRef ! msg1
bRef ! msg2

Актор B выполняет следующий код в обработчике сообщений:

case msg1 => 
    cRef ! msg3
    aRef ! msg4

Actor C выполняет следующий код в обработчике сообщений:

case msg3 => 
    aRef ! msg5

Могу ли я сделать следующие предположения (если есть):

  1. субъект B получает сообщение msg1, прежде чем получает сообщение msg2

  2. субъект A получает сообщение msg5, прежде чем получает сообщение msg4

И дополнительный вопрос, который, вероятно, приводит к пониманию вышеизложенного: Сообщение отправлено! оператор по сети действительно асинхронный или он ждет, пока получающий почтовый ящик его не получит? То есть делает линию

bRef ! msg1

блокировать, пока субъект B не получит сообщение в своем почтовом ящике или не создаст поток, который обрабатывает доставку и продолжит выполнение

bRef ! msg2

еще до того, как он узнает, что актер B получил msg1?

Ответы [ 2 ]

8 голосов
/ 01 июня 2011

Для (1) у вас есть гарантия, что диспетчер msg1 будет поставлен в очередь перед msg2.То, что происходит на самом деле, когда они ставятся в очередь, действительно зависит от того, какой диспетчер вы используете: http://akka.io/docs/akka/1.1.2/scala/dispatchers.html,, но в вашем случае, если B может принять оба сообщения, он всегда будет получать msg1 до msg2.

Для (2), нет, у вас нет этой гарантии.!Метод возвращается, как только диспетчер ставит сообщение в очередь, а не когда сообщение принимается почтовым ящиком целевого субъекта.Затем отправка выполняется в другом потоке и зависит от всех условий гонки.

Является ли сообщение, отправленное!оператор через сеть действительно асинхронный или он ждет, пока получающий почтовый ящик не получит его?

Вы можете использовать BoundedMailbox с локальными субъектами, чтобы показать, что постановка в очередь сообщений диспетчерам асинхронна с!:

class TestActor extends Actor {
  val mailboxCapacity = BoundedMailbox(capacity = 1)
  self.dispatcher = Dispatchers.newExecutorBasedEventDrivenDispatcher("test", 1, mailboxCapacity).build

  def receive = {
    case x: String => 
      Thread.sleep(1000)
      println("Received message")
    case _ => 
  }
}

val t = Actor.actorOf[TestActor]
t.start()

t ! "one"; t ! "two"; t ! "three"; println("Main thread");

Отпечатки:

scala>     t ! "one"; t ! "two"; t ! "three"; println("Main thread");
Received message
Main thread

scala> Received message
Received message

Это означает, что выполнение кода в главном потоке продолжается до того, как вы узнаете, будет ли доставлено сообщение.В этом случае отправка сообщения могла легко истечь, если мы установили pushTimeout на диспетчере и заставили Thread.sleep ждать дольше, чем время ожидания.

Сравните это с использованием !!:

scala>     t !! "one"; t !! "two"; t !! "three"; println("test");
Received message
Received message
Received message
test

Итак, помните об этом.Способ достижения (2) будет:

case msg1 =>
  cRef !! msg3
  aRef ! msg4 
1 голос
/ 01 июня 2011

Эрланг дает вам первую гарантию, но не вторую. Акка может дать вам и первую гарантию, но, конечно, не даст вам второй гарантии.

Я не знаю ответа на ваш вопрос.

...