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

Akka集群:如何在路由消息之前等待n个路由器向路由器注册,akka,akka-cluster,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 } 然后我使用集群单例启动一个actor,启动一个集群感知路由器: deployment { /parent/singleton/rou

我有一个需要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
}
然后我使用集群单例启动一个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个实例已经准备好了


<> P> <强> >问题是什么是等待所有<代码> NR的实例在开始向它们发送消息之前需要准备好RouTee实例?< /强>

< p>您可能需要考虑使用<代码> RealStEnMeNuppu回调。以下是一份相关报告的要点:

通过配置选项,您可以定义所需的成员数 在领导将“加入”成员的成员状态更改为“向上”之前:

您可以在
registerMemberUp
回调中启动参与者,该回调 将在当前成员状态更改为“Up”时调用, i、 e.集群至少有定义数量的成员


您可能想考虑使用<代码> RealStEnMeNuppu回调。以下是一份相关报告的要点:

通过配置选项,您可以定义所需的成员数 在领导将“加入”成员的成员状态更改为“向上”之前:

您可以在
registerMemberUp
回调中启动参与者,该回调 将在当前成员状态更改为“Up”时调用, i、 e.集群至少有定义数量的成员


好的,在深入研究集群之前,我可能应该更仔细地阅读基本文档

这个问题的答案是向路由器发送
GetRoutees
消息,然后处理响应以检查已经添加了多少路由

此处记录了
GetRoutees

将akka.routing.GetRoutees发送给路由器参与者将使其在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();
}
@覆盖
公共无效预启动()
{
ActorRef路由器=
getContext()
.actorOf(Props.empty().withRouter(FromConfig.getInstance()),
“路由器1”);
tell(GetRoutees.getInstance(),self());
}
@凌驾
公共接收createReceive()
{
返回
ReceiveBuilder.create()
.match(Routees.class,r->{
int noOfRoutees=r.getRoutees().size();
log().info(“路由数目:{}”,无路由);
如果(不超过3)
getSender().tell(GetRoutees.getInstance(),
getSelf());
其他的
分发消息(getSender());
})
.matchAny(o->log().info(
“哎呀,我不明白这条消息{}”,
o、 getClass())
.build();
}

好的,在深入研究集群之前,我可能应该更仔细地阅读基本文档

这个问题的答案是向路由器发送
GetRoutees
消息,然后处理响应以检查已经添加了多少路由

此处记录了
GetRoutees

将akka.routing.GetRoutees发送给路由器参与者将使其在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();
}
@覆盖
公共无效预启动()
{
ActorRef路由器=
getContext()
.actorOf(Props.empty().withRouter(FromConfig.getInstance()),
“路由器1”);
tell(GetRoutees.getInstance(),self());
}
@凌驾
公共接收createReceive()
{
返回
ReceiveBuilder.create()
.match(Routees.class,r->{
int noOfRoutees=r.getRoutees().size();
log().info(“路由数目:{}”,无路由);
如果(不超过3)
getSender().tell(GetRoutees.getInstance(),
getSelf());
其他的
分发消息(getSender());
})
.matchAny(o->log().info(
“哎呀,我不明白这条消息{}”,
o、 getClass())
.build();
}

我就是这么做的。我在
onMemberUp
中开始的是一个集群单例参与者,它在
preStart()方法中启动路由器(方法主体在我最初的问题中)。在相同的
preStart()
方法中,我开始向路由器发送消息。似乎基础路由没有及时启动。这就是为什么我在发送消息之前增加一些延迟会起作用,但我发现这种方法很脆弱。我已经扫描了文档,似乎正确的方法是“手动”启动routees,然后在其周围创建router。我会试试的。好吧,我得说我在这里不知所措。我尝试了组路由器路径。我在启动时立即在集群成员中创建worker,然后使用
registerMemberUp
hook启动集群singleton,启动路由器,开始向路由对象发送消息。如果我没有在创建路由器和发送消息之间添加延迟,那么所有消息都将发送到与路由器在同一节点上运行的一个路由器,如果我添加延迟,那么消息将被发送到所有节点上的所有工作进程。因此我不认为启动工作进程是问题,问题是路由器查找路由需要一些时间。一我
  Cluster.get(system).registerOnMemberUp(new Runnable() {
    @Override
    public void run() {
      // e.g. Send messages to cluster members
    }
  });
@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();
}