2017-06-27 1 views
0

Ich versuche, eine Nachricht an einen Singleton-Akteur zu senden, der auf einem Remote-Knoten durch einen anderen Akteur bereitgestellt wurde.Akka ClusterSingletonProxy zu einem remote bereitgestellten Singleton

Dies ist der Manager, der für ein memberUp Ereignis wartet, setzt dann Worker Akteur auf diesem Knoten und sendet dann die Singletons eine Nachricht:

object Manager extends App { 
    val sys = ActorSystem("mySys", ConfigFactory.load("application").getConfig("manager")) 
    sys.actorOf(Props[Manager], "manager") 
} 

class Manager extends Actor with ActorLogging { 
    override def receive: Receive = { 
    case MemberUp(member) if member.address != Cluster(context.system).selfAddress => 
     context.system.actorOf(ClusterSingletonManager.props(
     singletonProps = Props(classOf[Worker]), 
     singletonName = "worker", 
     terminationMessage = End, 
     role = Some("worker")).withDeploy(Deploy(scope = RemoteScope(member.address)))) 

     context.actorOf(ClusterSingletonProxy.props(
     singletonPath = s"/user/singleton/worker", 
     role = Some(s"worker")), "worker") ! "hello" 
    } 
    override def preStart(): Unit = { 
    Cluster(context.system).subscribe(self,classOf[MemberUp]) 
    } 
} 

Dies ist der Arbeiter:

object Worker extends App{ 
    ActorSystem("mySys", ConfigFactory.load("application").getConfig("worker")) 
} 

class Worker extends Actor with ActorLogging { 

    override def receive: Receive = { 
    case msg => 
     println(s"GOT MSG : $msg from : ${sender().path.name}") 
    } 
} 

Und die application.conf:

manager { 
    akka { 
    actor { 
     provider = "akka.cluster.ClusterActorRefProvider" 
    } 
    cluster { 
     auto-down-unreachable-after = 20s 
     seed-nodes = [ 
     "akka.tcp://[email protected]:2552" 
     ] 
     roles.1 = "manager" 

    } 
    remote.netty.tcp.port = 2552 

    } 
} 

worker { 
    akka { 
    cluster { 
     auto-down-unreachable-after = 20s 
     seed-nodes = [ 
     "akka.tcp://[email protected]:2552" 
     ] 
     roles.1 = "worker" 
    } 
    remote.netty.tcp.port = 2554 
    actor { 
     provider = "akka.cluster.ClusterActorRefProvider" 
    } 
    } 
} 

Der Arbeiter ist initialisiert (und Ich kann in den Protokollen die state change [Start -> Oldest] Nachricht sehen), aber die Nachricht, die vom Manager gesendet wird, kommt nie zum Arbeiter. Früher funktionierte es gut, als ich das Singleton auf dem Remote-Knoten deployte, aber jetzt möchte ich, dass der Manager es deployed.

Ich habe auch versucht, es als Kind des Managers bereitzustellen (mit Kontext statt Context.System) und änderte den Singleton-Pfad zu user/manager/singleton/worker, aber es hat nicht funktioniert.

Ich bin mit Akka 2.3.11

Edit: sbt-Datei:

name := "MyProject" 
version := "1.0" 
scalaVersion := "2.10.5" 
libraryDependencies += 
    "com.typesafe.akka" %% "akka-actor" % "2.3.11", 
    "com.typesafe.akka" %% "akka-cluster" % "2.3.11", 
    "joda-time" % "joda-time" % "2.0", 
    "com.typesafe.akka" %% "akka-contrib" % "2.3.11" 
+0

Könnten Sie bitte Ihre build.sbt posten? Es ist einfacher zu reproduzieren, ohne alle Bibliotheken zusammensuchen zu müssen. – thwiegan

+0

Ich habe meinen Beitrag mit der sbt-Datei bearbeitet –

+0

Danke, das Paket für den ClusterSingleton in 2.5 geändert und ich konnte nicht herausfinden, was es mit 2.3.11 war – thwiegan

Antwort

1

Also spielte ich ein bisschen herum mit verschiedenen Optionen von ClusterSingletonManager s zu schaffen und ich denke, die Bereitstellung von ihnen remote etwas innerhalb des Singleton-Musters brechen. Ich habe ein paar Indikatoren dafür gesammelt:

  • Da der Weg des ClusterSingletonManager auf den Arbeiter Knoten eine Remote-Bereitstellung ist /remote/akka.tcp/[email protected]:2552/user/worker ist. Ich glaube nicht, die Bibliothek kann/wird diese handhaben, da es /user/worker

  • erwartet Beim Versuch, die Nachricht von dem Master-Knoten im Debug-Modus mit ClusterSingletonProxy Protokoll gesendet heißt No singleton available, stashing message hello worker und Trying to identify singleton at akka.tcp://[email protected]:2552/user/worker/singleton (was nicht und Wiederholungen) -> Es sucht nach dem Singleton auf dem falschen Knoten, da kein Manager verfügbar ist und es offensichtlich nicht bemerkt, dass sich der Singleton auf dem Worker-Knoten befindet.

Beim Erstellen der ClusterSingletonManager auf den Arbeiter Knoten direkt alles wie erwartet funktioniert.

Sie hatten auch ein Problem mit der Benennung des Managers. Ihre singletonName ist worker und Ihr Manager selbst (der Schauspieler) hat keinen Namen. Wenn Sie den Proxy erstellen, verwenden Sie den Pfad /user/singleton/worker, aber der Pfad sollte wie folgt lauten: /user/{actorName}/{singletonName}. Also in meinem Code habe ich worker als actorName und singleton als singletonName verwendet.

Also hier ist mein Arbeitscode:

object Manager extends App { 
    val sys = ActorSystem("mySys", ConfigFactory.load("application").getConfig("manager")) 
    sys.actorOf(Props[Manager], "manager") 
} 

class Manager extends Actor with ActorLogging { 
    override def receive: Receive = { 
    case MemberUp(member) if member.address != Cluster(context.system).selfAddress => 
     context.actorOf(ClusterSingletonProxy.props(
     singletonPath = s"/user/worker/singleton", 
     role = Some("worker")), name = "workerProxy") ! "hello worker" 
    } 
    override def preStart(): Unit = { 
    Cluster(context.system).subscribe(self,classOf[MemberUp]) 
    } 
} 

object Worker extends App{ 
    val sys = ActorSystem("mySys", ConfigFactory.load("application").getConfig("worker")) 

    sys.actorOf(ClusterSingletonManager.props(
    singletonProps = Props(classOf[Worker]), 
    singletonName = "singleton", 
    terminationMessage = PoisonPill, 
    role = Some("worker")), name = "worker") 
} 

class Worker extends Actor with ActorLogging { 

    override def receive: Receive = { 
    case msg => 
     println(s"GOT MSG : $msg from : ${sender().path.name}") 
    } 
} 

application.conf und build.sbt gleich geblieben.

EDIT

Verstanden mit durch Verweis auf den Arbeiter Knoten (Berechnung, dass es ein Netzwerkpfad ist), um die ClusterSingletonProxy mit dem tatsächlichen Pfad zu arbeiten. Ich bin nicht sicher, ob ich das empfehlen würde, da ich bin immer noch nicht sicher, ob diese Bibliothek ausgelegt ist, die Lage sein, dies zu tun, aber es funktioniert zumindest in diesem minimal Beispiel:

object Manager extends App { 
    val sys = ActorSystem("mySys", ConfigFactory.load("application").getConfig("manager")) 
    sys.actorOf(Props[Manager], "manager") 
} 

class Manager extends Actor with ActorLogging { 
    override def receive: Receive = { 
    case MemberUp(member) if member.address != Cluster(context.system).selfAddress => 
     val ref = context.system.actorOf(ClusterSingletonManager.props(
     singletonProps = Props(classOf[Worker]), 
     singletonName = "singleton", 
     terminationMessage = PoisonPill, 
     role = Some("worker")).withDeploy(Deploy(scope = RemoteScope(member.address))), name = "worker") 

     context.actorOf(ClusterSingletonProxy.props(
     singletonPath = s"${ref.path.toStringWithoutAddress}/singleton", // /remote/akka.tcp/[email protected]:2552/user/worker/singleton 
     role = Some("worker")), name = "workerProxy") ! "hello worker" 
    } 
    override def preStart(): Unit = { 
    Cluster(context.system).subscribe(self,classOf[MemberUp]) 
    } 
} 

object Worker extends App{ 
    val sys = ActorSystem("mySys", ConfigFactory.load("application").getConfig("worker")) 
} 

class Worker extends Actor with ActorLogging { 

    override def receive: Receive = { 
    case msg => 
     println(s"GOT MSG : $msg from : ${sender().path.name}") 
    } 
} 
+0

Danke - es hat funktioniert. Es funktioniert jedoch nur für 1 Schauspieler. Wenn ich versuche, einen anderen Manager und einen anderen Worker hinzuzufügen, wo Manager2 einen zweiten Singleton-Worker2 implementiert, dann den Proxy startet und eine Nachricht sendet, erreicht die Nachricht nicht den Worker1 (der der aktive Singleton ist). Es ist merkwürdig, dass sie die Remote-Bereitstellung von Singletons nicht zulassen möchten, aber sie erlauben, mit Deploy auf ClusterSingletonManager-Requisiten aufzurufen. frage mich, ob es in neueren Versionen gleich ist. –

Verwandte Themen