Akka群集:在路由消息之前,如何等待n条路由向路由器注册

时间:2018-06-30 00:54:20

标签: akka akka-cluster

我有一个需要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所需路由实例准备就绪的正确方法是什么?

2 个答案:

答案 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();
}