3

I have a Scala application where I have several nodes. Each node has an ActorSystem with a main actor and each actor must have some ActorRef to certain actors (for example "Node 1" has "Actor3" and "Actor3" needs the ActorRef for "Actor7" and "Actor8" to do its work). My problem is that I don't know if another node ("Node2") has the "Actor1" or the "Actor7" I'm looking for.

My idea was to loop inside every MemberUp, using the ActorSelection several times and asking every new member if it has the actors I'm looking for. Is this the only way I can do it? Is there a way to do this more efficiently?

Fred Sobotka
  • 5,252
  • 22
  • 32
As As
  • 2,049
  • 4
  • 17
  • 33
  • if I am not misunderstanding you, why not use akka cluster singleton? Cluster Singleton — Akka Documentation http://doc.akka.io/docs/akka/snapshot/scala/cluster-singleton.html , you can hold the `Map[Address,List[ActorRef]]` like Fatih Donmez said or use that singleton to spawn child worker using remote router – mingchuno Nov 06 '15 at 16:17

2 Answers2

2

An alternative approach to ActorSelection can be lookup table. If you need to make lots of actor selection and actor creation is not so dynamic, it can be better solution.

On each node you can create a data structure like Map[String,List[String]] first key is Node name and List value is for actor refs in this node.

Trick is when any node has change for its actors (creating, stopping) another actor should notice other nodes about changes so any nodes have synchronised updated map.

If you guaranty it, then each node can lookup actor existence;

map.get(nodeName) match {
  case Some(n) => n.contains(actorName)
  case None => false
}
Fatih Donmez
  • 4,319
  • 3
  • 33
  • 45
  • But in a MemberUp, I have access to just the "member" parameter and it's a bit limited. I didn't understand quite well how to handle that map. – As As Nov 05 '15 at 13:26
  • Then how will you do actorselection? You need to have identifier for remote selection. I assumed you can send a message to node{id}/commandActor . CommandActor handle map operations and each node creates it. – Fatih Donmez Nov 05 '15 at 13:53
  • I know the names of the actors I need, so the idea was to use in the MemberUp the following line: `context.system.actorSelection(RootActorPath(member.address)/"user"/actorName);` – As As Nov 05 '15 at 13:57
  • Cool then just create another actor. It's responsible only for map operations. Then handle ActorCreated(nodeName,actorName), ActorDeleted(nodeName,actorName) .. On each command update local map. When you create/delete a new actor in a node send message to each nodes like `context.system.actorSelection(RootActorPath(member.address)/"user"/mapCommandActor) ! ActorCreated(myNodeName,createdActorName)` – Fatih Donmez Nov 05 '15 at 14:03
2

I've solved a very similar problem in our cluster by having a DiscoveryActor at a known path on every node. The protocol of the DiscoveryActor has

Register(name, actorRef)
Subscribe(name)
Up(name, actorRef)
Down(name, actorRef)

Each named actor sends a Register to its local DiscoveryActor which in turn broadcasts the Up to all local subscribers and all other DiscoveryActor's on other nodes, which in turn broadcast to their subscribers

The DiscoveryActor watches MemberUp/MemberDown to determine when to look for a new peer DiscoveryActor and broadcast its local registrations or broadcast Down for registrations of downed peers.

Arne Claassen
  • 14,088
  • 5
  • 67
  • 106