How to distribute actor creation by role

Hi,

I am using cluster sharding with four nodes (N1, N2, N3 and N4).

N1 and N2 - started with default role.
N3 and N4 - started with function role.

Below is the code,

ActorRef shardRegion = setupClusterSharding(system, "shardRegion", ReactorProperty.getRole());
private static ActorRef setupClusterSharding(ActorSystem actorSystem, String entityName, String role) {
        ClusterShardingSettings settings = ClusterShardingSettings.create(actorSystem).withRole(role);
        return ClusterSharding.get(actorSystem).start(
                entityName,
                ShardingActor.props(),
                settings,
                Message.messageExtractor()
        );
    }

whenever I send message to shardRegion it is distributing actor creation across all the four nodes not with roles. I mean, few actor creation I wanted to distribute only on N3 and N4 since the role is function but the distribution happens on all four nodes.

shardActor.tell(message, getSelf());

I don’t know how to control this so I am using ActorSelection to achieve this.

I am subscribing to cluster events so that I have control over Member Up and aExit events

    private void addMember(Member member) {
        Set<Address> value = new HashSet<>();
        String role =   member.getRoles().iterator().next();
        if (member.roles() != null &&  role!= null && nodes.get(role) != null) {
            value = nodes.get(member.roles().head());
            value.add(member.address());
        } else
            value.add(member.address());
        nodes.put(role, value);
    }
    private void removeMember(Member member) {
        Set<Address> value = new HashSet<>();
        String role =   member.getRoles().iterator().next();

        if (member.roles() != null && role != null && nodes.get(role) != null) {
            value = nodes.get(role);
            value.remove(member.address());
        }
        nodes.put(role, value);
    }
   
    private ActorSelection getShardActor(Set<Address> addresses) {
        if (addresses != null) {
            Iterator<Address> itr = addresses.iterator();
            if (itr.hasNext())
                return getContext().actorSelection(addresses.iterator().next() + "/system/sharding/shardRegion");
        }
        throw new NoSuchElementException();
    }

I am using below snippet to send messages

ActorSelection shardActor 

if (isFunction)
     shardActor = getShardActor(SupervisorActor.getNodes().get("function"));
else
    shardActor = getShardActor(SupervisorActor.getNodes().get("default"));

shardActor.tell(event, getSelf());

Is it correct way of implementation ?

Please guide me on this!!

I’m not quite sure what you mean, but because you are already creating the ClusterShardingSettings .withRole(role), these actors should already be created only on the nodes with this role. Listening to Cluster Up/Exited events or using ActorSelection should not be necessary for that.

Thanks @raboof

Yes, As you mentioned I am already creating ClusterShardingSetting with role.
But I don’t know how to distribute actor creation only on N3 and N4.

As per above snippet my startup will create shardRegion actor.

So If I send a message to this actor then it will be distributing actor creation, across all the four nodes.

shardActor.tell(message, getSelf());

What should I suppose to do to distribute actor creation only on N3 and N4.

If you only assign the function role to N3 and N4 by setting akka.cluster.roles = [ "function" ] there and not on N1 and N2, then actors should already be distributed only over those 2 roles.

If this is not working for you, could you perhaps share an example project showing your approach?

Thanks @raboof

I’ll share the source code link.

Kindly have a look and let me know your thoughts
https://github.com/anilkumble/AkkaClusterExample

Thanks

  • There’s no build files so I can’t run it
  • Where/how are you setting akka.cluster.roles?

To check whether akka.cluster.roles is set correctly, it might be useful to enable akka.log-config-on-start.