Я пытаюсь сделать 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, я больше не получаю ответа. Я также попытался посмотреть, что произойдет, если я только tell
ActorB
и продолжите в ActorA
, не заботясь о результатах. Что происходит, тогда я получаю сообщение от ActorB
, которое должно быть моим ответом на первоначальный запрос ... ActorB
, следовательно, отлично способен отправить обратно на ActorA
, но по какой-то причине Akka не будет использовать его в качестве ответа к моему оригинальному спросу ...
Можете ли вы предоставить код, который создает ActorRef, который вы передаете в ActorA? Кроме того, что такое 'remoteGenerator'? –
Я исправил опечатку, 'remoteGenerator' is remoteActor. Я также добавил код, который я использую, чтобы получить remoteActor из (ActorRef я передаю ActorA) - это результат «val actorRef = ...», который я выполняю на машине B – ErikT
Не могли бы вы показать, как 'sourceActor' и 'remoteActor' созданы? А именно: 'val sourceActor = ...' и 'val remoteActor = ...'. –