2015-12-25 2 views
1

Я пытаюсь сделать ask что-то актеру, созданному удаленно в SmallestMailboxPool, но я никогда не получаю ответа. Я чувствую, что это потому, что я отправляю сообщение на Router, но Routee - это актер, который отвечает - не зная точную внутренность запроса Акки, я могу представить, что ответ должен быть таким же, как там, где было отправлено сообщение к. С другой стороны, это кажется настолько рудиментарным, что я не могу себе представить, что это не сработает.Akka remoting - ask routee не возвращает ответ

Я использую рамку Play 2.3.x и Akka пульт 2.3.4

Актер установку У меня есть 2 машины с 2 актерами на этих машинах. Я постараюсь, чтобы этот пример был как можно более кратким.

машина A/актеру

Фактическое запроси инициируется на компьютере A, я добавил некоторые println заявления, чтобы показать актеру адреса. Код выглядит следующим образом.

class ActorA(remoteActor: ActorRef) extends Actor with ActorLogging { 
    ... 
    def receive() = { 
     case a: String => { 
      println("Remote actor: " + remoteActor) 
      println("Self: " + self) 
      // This is where I get a timeout because I never get a reply 
      Await.result((remoteActor ? a), timeout.duration) 
     } 
    } 
} 

Выход я получаю на компьютере A выглядит следующим образом:

Remote actor: Actor[akka.tcp://[email protected]:2552/user/actorB_6f9bac20-2302-4408-9a1b-feece8c20bc3#-1920529606] 
Self: Actor[akka://application/user/9df0190a-11fb-438c-9124-4869d015fc4d#-867250738] 

Обратите внимание, что ActorRef я передаю на ActorA (так называемый remoteActor), является val actorRef, что я создаю на компьютере B (см. ниже), имея MailboxPool.

машина В/В актер

На компьютере B, у меня есть актер B, который создается в SmallestMailboxPool обеспечением и получает сообщение от Actor A (через маршрутизатор), после чего он отвечает.

Создание выглядит следующим образом:

// Creation of the mailbox/Router 
val actorRef = Akka.system.actorOf(
    SmallestMailboxPool(1).props(
     // sourceActor is the actorRef of Actor A, living on machine A 
     Props(ActorB, sourceActor) 
    ), 
    name = java.util.UUID.randomUUID.toString 
) 
println("Mailbox is: " + actorRef) 

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

class ActorB(sourceActor: ActorRef) extends Actor with ActorLogging { 
    println("I am: " + self) 
    def receive() = { 
     case a: String => { 
      println("I got data from " + sender) 
      println("Sending it back to: " + sourceActor) 
      sourceActor ! d 
     } 
    } 
} 

Что я получаю от Actor B является следующие printlines:

Mailbox is Actor[akka://application/user/actorB_6f9bac20-2302-4408-9a1b-feece8c20bc3#-1920529606] 
I am Actor[akka://application/user/actorB_6f9bac20-2302-4408-9a1b-feece8c20bc3/$a#46262703] 
I got data from Actor[akka.tcp://[email protected]:2552/temp/$e] 
I am sending it back to: Actor[akka.tcp://[email protected]:2552/user/9df0190a-11fb-438c-9124-4869d015fc4d#-867250738] 

Так что я не понимаю, почему адрес актера от ActorA появляется как temp/$e на Acto rB. Как можно видеть, ActorB получает сообщение от ActorA, которое фактически отправляет его на маршрутизатор. ActorB затем по праву пытается ответить на ActorA, но всегда получает тайм-аут - это потому, что у ActorB есть другой адрес ActorRef/address, чем Router/Mailbox? Я также попытался отправить обратно на sender вместо заданного параметра sourceActor, но безрезультатно.

Я знаю, что могу запросить почтовый ящик для всех его маршрутов и отправить запрос прямо им (еще не пробовал это сделать), но это бросает вызов всей цели MailboxPool.EDIT: Пробовал это, не работает ни

EDIT:

Самая странная всей этой истории является то, что если я создаю ActorB на машине А, все работает просто (например, не удаленно.) В порядке - я могу задать номер ActorRef Router и получить правильный ответ. Как только ActorB создан на машине B, я больше не получаю ответа. Я также попытался посмотреть, что произойдет, если я только tellActorB и продолжите в ActorA, не заботясь о результатах. Что происходит, тогда я получаю сообщение от ActorB, которое должно быть моим ответом на первоначальный запрос ... ActorB, следовательно, отлично способен отправить обратно на ActorA, но по какой-то причине Akka не будет использовать его в качестве ответа к моему оригинальному спросу ...

+0

Можете ли вы предоставить код, который создает ActorRef, который вы передаете в ActorA? Кроме того, что такое 'remoteGenerator'? –

+0

Я исправил опечатку, 'remoteGenerator' is remoteActor. Я также добавил код, который я использую, чтобы получить remoteActor из (ActorRef я передаю ActorA) - это результат «val actorRef = ...», который я выполняю на машине B – ErikT

+0

Не могли бы вы показать, как 'sourceActor' и 'remoteActor' созданы? А именно: 'val sourceActor = ...' и 'val remoteActor = ...'. –

ответ

0

Мне удалось заставить его работать. Оказывается, я проходил мимо ActorRef до ActorB, на который он должен был послать, но в момент времени от ActorA кажется, что Akka делает своего рода временного актера, который действительно должен быть отправлен с ActorB (то есть я могу 'просто отправьте в ActorRef of ActorA, который я передал ActorB и сохранил ранее). Использование sender было для меня проблемой. (Хотя я все еще озадачен, почему sender на самом деле не был моим ActorA).

Мой реальный прецедент слишком сложный, чтобы делиться на SO, но я сделал небольшой пример (где эта проблема не возникает - все работает) для заинтересованных людей: https://github.com/ErikTromp/AkkaRemoteAskTest. Он также использует библиотеку Playter Iteratee, так как это тоже часть моего использования.

Смежные вопросы