2015-12-25 3 views
1

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 tellActorB 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 ...

+0

Pouvez-vous fournir le code qui produit l'ActorRef que vous transmettez à ActorA? Aussi, qu'est ce que 'remoteGenerator'? –

+0

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

+0

Pouvez-vous montrer comment 'sourceActor' et 'remoteActor' sont créés? A savoir, 'val sourceActor = ...' et 'val remoteActor = ...'. –

Répondre

0

J'ai réussi à le faire fonctionner. Il se trouve que je passais un ActorRef à ActorB auquel il était censé envoyer, mais à la demande d'ActorA, il semble qu'Akka crée une sorte d'acteur temporaire qui doit être envoyé à ActorB (ie je peux Il ne suffit pas d'envoyer à ActorRef d'ActorA que j'ai transmis à ActorB et stocké plus tôt). En utilisant sender était un correctif pour moi. (Bien que je suis toujours perplexe pourquoi sender n'était pas mon ActorA).

Mon cas d'utilisation réelle est beaucoup trop complexe à partager sur SO, mais j'ai fait un petit exemple (où ce problème ne se produit pas - tout fonctionne) pour les personnes intéressées: https://github.com/ErikTromp/AkkaRemoteAskTest. Il utilise aussi la bibliothèque Iteratee de Play, car cela fait aussi partie de mon cas d'utilisation.