Akka.net: Access remote Actors in Cluster
Asked Answered
M

1

5

In an clustered environment I have a seed node and node1 and node2.

From node1 I want to send a message to an Actor which has been created on node2. The local path to this node on node2 is akka:MyAkkaSystem/user/AnActor.

Now I want to send a message from an Actor from node1 to this specific actor by using an ActorSelection like that:

var actorSystem = ActorSystem.Create("MyTestSystem");
var c = actorSystem.ActorSelection("/user/ConsoleReceiver");
c.Tell("Hello World");

On node2 the actor has been created like that:

var actorSystem = ActorSystem.Create("MyTestSystem");
            var r = actorSystem.ActorOf(Props.Create<MessageReceiver>(), "ConsoleReceiver");
            Console.WriteLine(r.Path);
            Console.ReadLine();
            actorSystem.Terminate().Wait();

Unfortunately this does not work out since the attempt ends in dead letters.

The HOCON configuration on node2 looks like that:

akka {
    actor {
      provider = "Akka.Cluster.ClusterActorRefProvider, Akka.Cluster"                  
      deployment {                  
      }              
    }

    remote {
      log-remote-lifecycle-events = DEBUG
      log-received-messages = on

      helios.tcp {
        transport-class = "Akka.Remote.Transport.Helios.HeliosTcpTransport, Akka.Remote"
            applied-adapters = []
            transport-protocol = tcp       
        hostname = "127.0.0.1"
        port = 0
      }
    }            

    cluster {
      #will inject this node as a self-seed node at run-time
      seed-nodes = ["akka.tcp://[email protected]:4053"] #manually populate other seed nodes here, i.e. "akka.tcp://[email protected]:4053", "akka.tcp://[email protected]:4044"
      roles = [crawler]
    }
  }

As seed node I am using lighthouse. From connection point of view everything seems to work out. The seed has been found and each node got has received a welcome message.

I thought I had location transparency on a Cluster and could reach remote resources as if they where local.

Mushroom answered 25/2, 2016 at 17:24 Comment(0)
D
8

I thought I had location transparency on a Cluster and could reach remote resources as if they where local.

This is not so easy. Consider following scenario: What if you've created an actor on both nodes under the same path. If you'll try to use relative path - without showing which node you have in mind - which of the actor's should receive the message?.

Using basic cluster capabilities you can choose node easily using Context.ActorSelection(_cluster.ReadView.Members.Single(m => /* which node you want to choose */).Address + "/user/ConsoleReceiver");. Cluster extension gives you a read view data with info about all members visible from current node.

There are many ways to send message to another actor, without having to know on which node it lives.

First approach is to use Akka.Cluster.Tools cluster singleton feature - it allows you to create at most one instance of an actor present in the cluster. In case of node failures it will migrate to another node. Be aware that this solution shouldn't be used, if you want to have many actors working that way. It's more for distinct, special-case actors.

Second approach is to use Akka.Cluster.Tools Distributed Pub/Sub feature to broadcast cluster-wide events across actors in the cluster subscribed to specific topic without worrying of their actual location. This is good choice for message broadcasting scenarios.

Last approach is to use Akka.Cluster.Sharding feature which manages actors lifecycle automatically - you don't need to create actors explicitly - it's also able to route messages to them from anywhere in the cluster and can rebalance them across many cluster nodes when needed.

Deneendenegation answered 25/2, 2016 at 18:13 Comment(7)
Well thanks. However, I thought the nodes were connected to each other due to Cluster gossip. So if the nodes are connected, why can't I address them directly?Mushroom
What do you mean by directly? In the first paragraph I've described direct access to actor on a node.Deneendenegation
Well it seemed as if you had to go a long way around to get to remote actors by querying the cluster, singleton, sharding, pub/sub etc. (which are great features). But since the nodes are connected already isn't there an easier way by saying: ActorSelection([role of node]/[path to actor]) or making it transparent with some nifty HOCON magic on the client side?Mushroom
You can extract this information easily from cluster.ReadView.Members - they already contain info about addresses and roles of each cluster node. Or you could probably use cluster group routers for that.Deneendenegation
That's it: group routers. Thx.Mushroom
For anyone who visits this page recently, ReadView has been depreciated from the cluster object, you can now use State to access the members list.Milford
Can we get count of entity actors in actor cluster??Like thisMontevideo

© 2022 - 2024 — McMap. All rights reserved.