2016-05-01 2 views
1

Ich weiß, dass Sie Nachrichten senden können und eine Antwort von außerhalb eines Schauspielers erhalten, wenn Sie ask (? Syntax) verwenden. Das Problem ist, ich weiß nicht, ob dies getan werden kann, wenn der Schauspieler entfernt ist. Mit "außerhalb eines Schauspielers" meine ich einen normalen Nicht-Schauspieler-Code. Kann ein Nicht-Schauspieler mit einem entfernten Schauspieler sprechen?Kann man mit einem entfernten Akteur von einem Nicht-Akteur kommunizieren?

[] ist die Prozessgrenze und Großschreibung bedeutet, dass es ein Akteur ist. Zuvor war der Aufbau dieser und funktioniert gut:

[a] [B:

[einB]

jedoch jetzt B Fern machen Ich versuche,]

Ich könnte es wahrscheinlich funktionieren, wenn ich [ein] einen lokalen Akteur geben würde, aber das sollte nicht notwendig sein.

In eine gibt es keine ActorContext, nur eine ActorSystem. Hier ist der Code, den ich zu verwenden Ich versuche (remote ist B):

val systemName = "THIS_UNIVERSE" 
// other vals: remoteIP, remotePort, remoteActorName - all to do with B 
val actorSystem = ActorSystem(systemName) 
... 
val str = s"akka.tcp://[email protected]$remoteIP:$remotePort/user/$remoteActorName" 
actorSystem.actorSelection(str).resolveOne().onComplete { 
    ... 
} 

Wie Sie auch die Syntax machen nicht viel Sinn sehen: Es gibt bereits ein actorSystem, doch im Protokoll String systemName Bedürfnisse verwendet werden.

Ist die Kommunikation mit einem entfernten Akteur von einem Nicht-Akteur möglich? Ich habe keine Beispiele als Referenz gefunden.

Ich weiß tatsächlich, dass B läuft und tatsächlich hat es bereits einen anderen Akteur, der in der Lage ist, es zu finden und mit ihm zu kommunizieren.

Für den Zweck dieser Frage habe ich gerade ein eigenständiges Scala-Programm eingerichtet, das einen Akteur erstellt und versucht, einen actorRef auf B zu erhalten, in ähnlicher Weise wie oben beschrieben. Aber keine Freude:

Actor not found for: ActorSelection[Anchor(akka://THIS_UNIVERSE/deadLetters), Path(/user/MyPLC)] 

Ist es der Fall, dass dieses Standalone-Programm benötigt, eine application.conf zur Verfügung haben geladen werden? d. h. ohne eine solche Datei ist es nicht möglich, entfernte Akteure zu finden?

Großartig - das Standalone-Programm kann den Remote-Actor finden, wenn eine src/main/resources/application.conf Datei vorhanden ist, die sbt abholen kann.

Also zurück zur ursprünglichen Frage: [a] per Definition wird keine application.conf Datei in seinem Klassenpfad haben, da es kein Akteur ist. Allerdings werde ich eins hinein und sehen, ob es hilft ...

Das hat geholfen! In diesem Fall wurde application.conf an die Wurzel einer der abhängigen JAR-Dateien gesetzt.

Also die Antwort auf die Frage ist, dass Sie von einem Nicht-Akteur kommunizieren können, aber Sie brauchen immer noch die meisten Akteure Zeug - die Schauspieler JAR-Dateien und eine application.conf auf dem Klassenpfad.

Antwort

3

Ja, Sie sollten in der Lage sein.

Wenn Sie von einem lokalen Akteur mit der Gegenstelle kommunizieren können, [A] [B], senden Sie B eine Nachricht an A, und drucken Sie den Absenderpfad, um sicherzustellen, dass Sie den richtigen Pfad haben.

In Bezug auf die Syntax ist systemName der Name des Remote-Actor-Systems. actorSystem In Ihrem Beispiel ist das lokale Akteursystem.

Sie könnten Ihren Nicht-Schauspieler-Code fragen Sie den lokalen Schauspieler für die ref. Zum Beispiel:

val remoteRefFuture = A ? GetRemoteAddress 
remoteRefFuture.mapTo[ActorRef].foreach { B => B ! Xyz } 

überprüfen Sie die IP-Adresse in dem Weg und stellen Sie sicher, sie paßt genau die IP-Adresse oder einen Hostnamen Sie in der Remotekonfiguration auf der Remote-Seite verwenden.

Hier ist ein kleines ausführbares Beispiel. Führen Sie zwei Instanzen dieser App aus. Starten Sie den ersten mit dem Befehlszeilenparameter 2550. Dann starten Sie die zweite mit 2551.

import akka.actor.{Actor, ActorSystem, Props} 
import com.typesafe.config.ConfigFactory 
import akka.pattern.ask 
import akka.util.Timeout 

import scala.concurrent.Await 
import scala.util.Success 
import scala.concurrent.duration._ 
import scala.concurrent.ExecutionContext.Implicits.global 

object AskRemote extends App { 
    val port = args(0).toInt 
    val configStr = 
    s""" 
     |akka { 
     | actor { 
     | provider = "akka.remote.RemoteActorRefProvider" 
     | } 
     | remote { 
     | enabled-transports = ["akka.remote.netty.tcp"] 
     | netty.tcp { 
     |  hostname = "localhost" 
     |  port = $port 
     | } 
     | } 
     |} 
     """.stripMargin 
    val config = ConfigFactory.parseString(configStr) 
    val system = ActorSystem(s"system$port", config) 

    if (port == 2550) { 
    system.actorOf(Props(new MyActor), "myActor") 
    system.awaitTermination() 

    } else { 
    implicit val timeout = Timeout(5.seconds) 
    val path = s"akka.tcp://[email protected]:2550/user/myActor" 

    system.actorSelection(path).resolveOne().onComplete { 
     case Success(ref) => 
     val fut = ref ? "hello" 
     println(Await.result(fut, 5.seconds)) 
     system.shutdown() 
    } 
    } 
} 

class MyActor extends Actor { 
    def receive = { 
    case s: String => 
     println(s"got $s") 
     sender() ! s"you sent $s" 
     context.system.shutdown() 
    } 
} 
+0

Hier haben Sie [** A **] einen Schauspieler gemacht. Aber [** a **] ist nur ein normaler Nicht-Akteur, der Zugang zu [** B **] benötigt. [** a **] ist nur ein Prozess, der * synchron * (mit '?' und 'Await') Fragen von [** B **] stellen möchte, was * hardware * ist. –

+0

Ich folge nicht - du sagtest "Großschreibung bedeutet, dass es ein Schauspieler ist" und dein 'str' Pfad Beispiel ist ein Pfad zu einem Schauspieler. Ich schlage vor, entweder 1) einen lokalen Akteur vorübergehend einzurichten, nur um zu überprüfen, ob der Remote-Pfad korrekt ist, oder 2) einen lokalen Actor als Vermittler zwischen dem Remote-Code und dem Nicht-Actor-Code zu verwenden. Sie werden ein Akteursystem auf der lokalen Seite brauchen, um '' '' '' 'ask'' zu verwenden, es wird nicht schaden, einen lokalen Schauspieler vermitteln zu lassen. – sourcedelica

+0

Nur eine Notiz hinzugefügt, um sicherzustellen, dass die IP-Adresse im Pfad korrekt ist. – sourcedelica