akka cluster how to wait for all routees to start


akka cluster how to wait for all routees to start



I have an Akka cluster that requires 3 nodes:


cluster {
seed-nodes = [
"akka.tcp://ClusterSystem@127.0.0.1:2551"
,"akka.tcp://ClusterSystem@127.0.0.1:2552"]

min-nr-of-members = 3
}



And then I use Cluster Singleton to start an actor, that starts a cluster aware router:


deployment {
/parent/singleton/router1 {
router = round-robin-pool
nr-of-instances = 3
cluster {
enabled = on
max-nr-of-instances-per-node = 1
allow-local-routees = on
}
}



This is how I initialize the singleton:


@Override
public void preStart()
{
ActorRef router =
getContext().actorOf(
WorkerActor.props().withRouter(FromConfig.getInstance()),
"router1");

Runnable r = () -> {
for (int i = 0; i < 20; i++) {
WorkerActor.Message message = WorkerActor.Message.addAccount(
WorkerActor.Account.of("username_" + i,
"password_" + i)
);

router.tell(message, ActorRef.noSender());
}
};

getContext().getSystem().scheduler()
.scheduleOnce(Duration.ZERO, r,
getContext().dispatcher());
}



When I start 3 nodes of the cluster, the singleton is created and starts sending messages to its routees, but it seems that there's only one existing at that moment, so all messages go to that one. What I want is to wait for 3 routees to be ready and then round robin messages between them.



The only way I could achieve it so far is to add a delay to scheduleOnce like this


scheduleOnce


getContext().getSystem().scheduler()
.scheduleOnce(Duration.ofSeconds(5) , r,
getContext().dispatcher());



But that's like crossing your fingers that the 3 instances will be ready before you start sending the messages.



So the question is what is a proper way of waiting for all nr-of-instances required routee instances to be ready before start sending messages to them?


nr-of-instances




1 Answer
1



You might want to consider using the registerOnMemberUp callback. Below are highlights from a relevant Akka doc:


registerOnMemberUp



With a configuration option you can define required number of members
before the leader changes member status of ‘Joining’ members to ‘Up’.:


akka.cluster.min-nr-of-members = 3



You can start the actors in a registerOnMemberUp callback, which
will be invoked when the current member status is changed to ‘Up’,
i.e. the cluster has at least the defined number of members.


registerOnMemberUp


Cluster.get(system).registerOnMemberUp(new Runnable() {
@Override
public void run() {
// e.g. Send messages to cluster members
}
});





This is kind of what I am doing. What I am starting in onMemberUp is a cluster singleton actor that starts the router in its preStart() method (the method body is in my original question). In the same preStart() method I am starting to send messages to the router. It seems that the underlying routees are not started in time. So that's why it's working if I add some delay before sending the messages, but I find this approach brittle. I've scanned the documentation and what seems to be the right approach is to start the routees 'by hand' and then create router around them. I will try that.
– artur
yesterday


onMemberUp


preStart()


preStart()






By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Comments

Popular posts from this blog

paramiko-expect timeout is happening after executing the command

Export result set on Dbeaver to CSV

Opening a url is failing in Swift