我有一个需要3个节点的Akka群集:
cluster {
seed-nodes = [
"akka.tcp://ClusterSystem@127.0.0.1:2551"
,"akka.tcp://ClusterSystem@127.0.0.1:2552"]
min-nr-of-members = 3
}
然后我使用Cluster Singleton来启动一个actor,它会启动一个支持集群的路由器:
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
}
}
这是我初始化单例的方式:
@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());
}
当我启动集群的3个节点时,将创建单例并开始向其路由发送消息,但是此时似乎只有一个,因此所有消息都发送到该路由。我想要的是等待3条路由准备好,然后在它们之间轮循消息。
到目前为止,我唯一能实现的方法就是像这样向scheduleOnce
添加延迟
getContext().getSystem().scheduler()
.scheduleOnce(Duration.ofSeconds(5) , r,
getContext().dispatcher());
但是,这就像在您的手指上一样,在开始发送消息之前,这3个实例已经准备就绪。
所以问题是,在开始向其发送消息之前,等待所有nr-of-instances
所需路由实例准备就绪的正确方法是什么?
答案 0 :(得分:2)
您可能要考虑使用registerOnMemberUp
回调。以下是相关Akka doc中的要点:
使用配置选项,您可以定义所需的成员数 领导者将“加入”成员的成员身份更改为“注册”之前。
akka.cluster.min-nr-of-members = 3
您可以在
registerOnMemberUp
回调中启动参与者, 当前会员状态更改为“上”时,将调用, 即集群至少具有定义的成员数。
Cluster.get(system).registerOnMemberUp(new Runnable() {
@Override
public void run() {
// e.g. Send messages to cluster members
}
});
答案 1 :(得分:0)
好的,在进行集群学习之前,我可能应该更仔细地阅读基本文档。
这个问题的答案是向路由器发送GetRoutees
消息,然后处理响应以检查已经添加了多少路由。
GetRoutees
记录在这里:https://doc.akka.io/docs/akka/current/routing.html#management-messages
将akka.routing.GetRoutees发送到路由器actor将使其在akka.routing.Routees消息中发回当前使用的路由。
实现看起来像这样:
@Override
public void preStart()
{
ActorRef router =
getContext()
.actorOf(Props.empty().withRouter(FromConfig.getInstance()),
"router1");
router.tell(GetRoutees.getInstance(), self());
}
@Override
public Receive createReceive()
{
return
ReceiveBuilder.create()
.match(Routees.class, r -> {
int noOfRoutees = r.getRoutees().size();
log().info("No of routees: {}", noOfRoutees);
if (noOfRoutees < 3)
getSender().tell(GetRoutees.getInstance(),
getSelf());
else
distributeMessages(getSender());
})
.matchAny(o -> log().info(
"oops, I don't understand this message {}",
o.getClass()))
.build();
}