Is there a way to get all instantiated actors currently available on a given node in Akka.NET
Asked Answered
O

1

6

I have the following code in my application which creates an instance of an Akka.NET actor in my cluster as such:

_actorSystem = ActorSystem.Create("mycluster");
_actoraActor = this._actorSystem.ActorOf<ActorA>();

Note that I deliberately omit the name property as I intend to create N actors of type ActorA and don't want to manage the names. Running the above I end up with an actor which has an ID that looks like this:

akka://mycluster/user/$a#1293118665

The problem I run into is trying to determine the Actor path from a different node. So for example I have tried doing the following:

public class ActorB : ReceiveActor
{
    private readonly Cluster Cluster = Akka.Cluster.Cluster.Get(Context.System);


    public ActorB()
    {

        this.Receive<ActorIdentity>(this.IdentifyMessageReceived);
        this.ReceiveAsync<ClusterEvent.MemberUp>(this.MemberUpReceived);
    }

    protected override void PreStart()
    {
        this.Cluster.Subscribe(this.Self, ClusterEvent.InitialStateAsEvents, new[]
        {
            typeof(ClusterEvent.IMemberEvent),
            typeof(ClusterEvent.UnreachableMember)                
        });
    }

    protected override void PostStop()
    {
        this.Cluster.Unsubscribe(this.Self);
    }

    private async Task<bool> MemberUpReceived(ClusterEvent.MemberUp obj)
    {
        if (obj.Member.HasRole("actora"))
        {
            //!The problem is here.
            //ALL YOU ARE PROVIDED IS THE NODE ADDRESS:  
            //Obviously this makes sense because it's the node that has come alive
            //and not the instances themselves.

            string address = obj.Member.Address.ToString();
            //akka.tcp://mycluster@localhost:666
            Context.ActorSelection(address).Tell(new Identify(1));
        }

        return true;
    }

    private bool IdentifyMessageReceived(ActorIdentity obj)
    {
        return true;
    }
}

Where via leveraging of the cluster MEMBER-UP event I try to send an Identify request to the new member but the problem I run into is the ClusterEvent.MemberUp object provided does not contain information regarding the actors within the node but only appears to contain a node reference that looks like this:

akka.tcp://mycluster@localhost:666

Which makes perfect sense because its the node that has come online, not an actor.

If I change my code to use a named actor:

_actorSystem = ActorSystem.Create("mycluster");
_actoraActor = this._actorSystem.ActorOf<ActorA>("actora");

I can then successfully query the service how I need. This is what you would expect when you have a named actor but there appears to be no way to actually externally determine instances of running actors on a node.

So, when using N instances of unnamed actors what are the correct steps to identify references to the actors you are interested in, specifically when the actors have been generated without a name?

EDIT:

I've decided to restate the question because I didn't adequately describe it initially. The correct expression of this question is:

"Is there a way to get all instantiated actors currently available on a given node from a external actor when all you have is the node path?"

To me it just seems like this should be something built into the base framework UNLESS there is some sort of design consideration that I don't fully understand.

I also note that I think it's likely the correct approach to my particular problem might just be that I am trying to do a Pub/Sub and this https://getakka.net/articles/clustering/distributed-publish-subscribe.html is more appropriate.

Ouellette answered 25/6, 2018 at 16:43 Comment(4)
I...don't want to manage the names... This is the crux of your problem. The last time we had to spin up N actors in Service Fabric we kept a list of the actor identifiers so we could manage them. Not doing this will make your job much more difficult, as you are learning.Prebendary
@DanWilson Fair enough and that's a valid point that I have considered but prior to moving in the direction you're suggesting I'd still like to know how to resolve this issue or be confident that there is in-fact no solution. I mean the counter argument is that there MUST be a reason they created a parameterless constructor for that method right?! If its not for this exact reason then why else?Ouellette
@MaximGershkovich, they created a parameter-less constructor for times when you don't care about the actor's name/path. Also, you can always get an actor's path by using the IActorRef's Path property: _delegatorActor.PathGonick
@NicholasReynolds I understand that I can get the path property at the time of instantiation BUT I can't get it on the other node.Ouellette
G
6

I think for your purposes here you should consider leveraging the actor hierarchy.

Instead of creating a top-level actor with a randomly assigned name, create a parent with a hard-coded name:

_actorSystem = ActorSystem.Create("mycluster");
_delegatorParent = this._actorSystem.ActorOf<ParentActorA>("parent");

This parent actor can spawn any number of children, and it can spawn children in response to incoming messages:

_delegatorParent.Tell(new WorkItem("someWork", 1200));

This could cause the parent to create a child actor that actually executes the work:

public class ParentActorA{
    public ParentActorA(){
       Receive<WorkItem>(x => {
          // create new child to carry out the work
          var delegatorActor = Context.ActorOf<ActorA>();
          delegatorActor.Forward(x);
       });
    }
}

This gives you a fixed entry point into this node / family of actors while still having the ability to spin up new actors that don't have specific names. Just look up the parent with the static name, not the children who execute the work.

While you're at it you may also want to take a look at pool routers and the child per entity pattern in Akka.NET.

Gravimeter answered 27/6, 2018 at 14:0 Comment(2)
Appreciate the detailed response I will take a look at that link too, thank you. Yes, I am aware that I can start doing 'tricks' like what you describe above to resolve the issue of 'node management'. I didn't express my question 100% correctly; fundamentally I just wanted to confirm if there is a way to list all the given actor instances currently available under a node.Ouellette
Ah, yes there is using wildcard ActorSelections - getakka.net/articles/concepts/… We built a commandline tool for managing Akka.NET nodes that uses this technique to print out actor hierarchies, including ones on remote machines: cmd.petabridge.com/articles/commands/…Gravimeter

© 2022 - 2024 — McMap. All rights reserved.