J'essaie de ask
quelque chose à un acteur qui a été créé à distance dans un SmallestMailboxPool
mais je ne semble jamais obtenir une réponse. Mon sentiment est que c'est parce que j'envoie le message au Router
, mais le Routee
est l'acteur qui répond - ne connaissant pas les internes exacts de la requête d'Akka, j'imagine que la réponse doit être la même que celle où le message a été envoyé à. D'un autre côté, cela semble si rudimentaire que je ne peux pas imaginer que ça ne marcherait pas.Akka remoting - demander routee ne renvoie pas la réponse
J'utilise le cadre de lecture 2.3.x et Akka à distance 2.3.4
Acteur Configuration J'ai 2 machines avec 2 acteurs sur ces machines. Je vais essayer de garder l'exemple aussi bref que possible.Machine A/Acteur A
La réelle ask est lancé sur la machine A, j'ai ajouté quelques println
déclarations pour montrer les adresses des acteurs. Le code est comme suit.
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)
}
}
}
La sortie Je reçois sur la machine A est la suivante:
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]
Notez que le ActorRef
je passe à ActorA (appelé remoteActor
), est le val actorRef
que je crée sur la machine B (voir ci-dessous), ayant le MailboxPool.
machine B/Acteur B
sur la machine B, j'ai un acteur B qui est créé dans un SmallestMailboxPool et recieves le message de l'acteur A (via le routeur), après quoi il répond.
La création est la suivante:
// 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)
L'acteur réel B effectue les opérations suivantes:
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
}
}
}
Ce que je veux de l'acteur B est les PRINTLINES suivantes:
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]
Donc ce que je ne comprends pas, c'est pourquoi l'adresse de l'acteur ActorA apparaît comme temp/$e
sur Acto Le côté de rB. Comme on peut également le voir, ActorB reçoit le message d'ActorA, qui l'envoie réellement au routeur. ActorB tente alors légitimement de répondre à ActorA, mais il obtient toujours un timeout - est-ce parce que ActorB a une ActorRef/adresse différente de celle du Router/Mailbox? J'ai également essayé de renvoyer à sender
au lieu du sourceActor
donné par paramètre, mais en vain.
Je sais que je peux demander à la boîte aux lettres pour toutes ses routes et envoyer une demande directement à eux (n'ont pas encore essayé ceci), mais cela défie l'objectif entier d'un MailboxPool.EDIT: J'ai essayé cela, ne fonctionne pas non plus
EDIT:
Le plus étrange de toute cette histoire, est que si je crée ActorB
sur la machine A, tout fonctionne (par exemple, pas à distance.) bien - je peux demander ActorRef
du routeur et j'obtiens une réponse appropriée. Dès que ActorB
est créé sur la machine B, je n'ai plus de réponse. J'ai également essayé de voir ce qui se passe si je juste tell
ActorB
et continuer dans ActorA
sans souci du résultat. Ce qui se passe alors, c'est que je reçois le message de ActorB
qui devrait être ma réponse à l'original ... à mon demande originale ...
Pouvez-vous fournir le code qui produit l'ActorRef que vous transmettez à ActorA? Aussi, qu'est ce que 'remoteGenerator'? –
J'ai corrigé la faute de frappe, 'remoteGenerator' est remoteActor. J'ai aussi ajouté le code que j'utilise pour obtenir remoteActor (l'ActorRef que je transmets à ActorA) - c'est le résultat du 'val actorRef = ...' que j'exécute sur la machine B – ErikT
Pouvez-vous montrer comment 'sourceActor' et 'remoteActor' sont créés? A savoir, 'val sourceActor = ...' et 'val remoteActor = ...'. –