Последовательность доставки сообщений в актерах akka

Я новичок в 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)

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

bRef ! msg1
bRef ! msg2

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

case msg1 => 
    cRef ! msg3
    aRef ! msg4

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

case msg3 => 
    aRef ! msg5

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

  1. актор B получает msg1 до того, как он получит msg2

  2. актор А получает msg5 до того, как он получит msg4

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

bRef ! msg1

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

bRef ! msg2

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


person Grozz    schedule 01.06.2011    source источник


Ответы (2)


Для (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 
person David McLaughlin    schedule 01.06.2011
comment
На самом деле вы не обращались к 1. и 2., хотя вы можете сделать вывод, что 2. не выполняется из того, что вы показали. Однако это не касается 1. даже косвенно. - person Rex Kerr; 01.06.2011
comment
Ты прав. Я изменил свой ответ, чтобы ответить на конкретный вопрос, на который я отвечал. - person David McLaughlin; 01.06.2011
comment
Вы уверены, что для достижения (2) мне также не нужно менять код C актера на aRef !! сообщение5? - person Grozz; 02.06.2011
comment
Можете ли вы объяснить, что делает !!, или дать ссылку на страницу документации Akka об этом? Видимо ждет, как и ?, но ни в гугле, ни в исходниках акки ничего про это не могу найти. - person chbrown; 11.11.2012
comment
@chbrown когда-нибудь разберусь !! - person Andrew Cassidy; 08.03.2014

Erlang дает вам первую гарантию, но не вторую. Akka может дать вам и первую гарантию, но точно не даст вам вторую гарантию.

Я не знаю ответа на ваш дополнительный вопрос.

person Daniel C. Sobral    schedule 01.06.2011