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
}
});
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.
This is kind of what I am doing. What I am starting in
onMemberUp
is a cluster singleton actor that starts the router in itspreStart()
method (the method body is in my original question). In the samepreStart()
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