管理阿卡的儿童演员地图的正确方法是什么?

时间:2017-04-12 19:47:11

标签: akka

假设我有一个演员负责根据某个键将消息路由到子actor的集合,因此它的内部状态如下所示:

Map<String, ActorRef> children;

除路由消息外,父actor还必须支持添加和删除操作:

if(message instanceOf Add) {
    children.put(message.getKey(), getContext().actorOf(childProps, message.getKey()));
} else if (message instanceOf Remove) {
    getContext().stop(children.get(message.getKey());
    children.remove(message.getKey());
} else if (message instanceOf RouteToChild) {
    children.get(message.getKey()).forward(message, getContext());
}

希望上面的代码足以让我了解我正在尝试做的事情。请注意,我使用map键作为子actor的名称。问题是上面的模式不能快速连续地为同一个键处理添加,删除和添加消息的情况 - 它经常在第二个添加时失败:

akka.actor.InvalidActorNameException: actor name [...] is not unique!

显然,在删除消息上停止子actor是异步的,这就是为什么它不起作用,我很难看到解决方案是什么。我已经注意到Akka docs中的以下几点,它完全描述了我的问题:

  

虽然以后可以使用相同的路径[...]创建演员,但这不是一个好习惯[...]。

     

在非常具体的情况下做这件事可能是正确的,但请确保将此处理精确地限制在演员的主管,因为这是唯一可以可靠地检测名称的正确注销的参与者,在此之前创建新生儿将失败。

那么,重复使用actor路径(使用map键作为actor名称)在这里做正确的事情是什么?如果是这样,我如何“可靠地检测到名称的正确注销”?如果没有,我应该为每个演员姓名分配一个UUID吗?如果孩子是持久性演员,这会导致问题(因为可以在前一个孩子被正确终止之前创建具有相同持久性id的新孩子)吗?

1 个答案:

答案 0 :(得分:1)

您可以watch ActorRef的状态在Actor被终止时获得通知。如果已发送终止但您的主管尚未收到确认,则ActorRef被视为“陈旧”。

如果Add进入陈旧的Actor,那么您只需再次发送添加给自己,希望终止最终完成:

HashSet<String> staleActorRefs = new HashSet<String>();

if(message instanceOf Add) {
    if(staleActorRefs.contains(message.getKey())) {
      getSelf().forward(message, getContext()); 
    } else {
      children.put(message.getKey(), getContext().watch(getContext().actorOf(childProps, message.getKey())));
    }
} else if (message instanceOf Remove) {
    getContext().stop(children.get(message.getKey());
    staleActorRefs.add(message.getKey());
    children.remove(message.getKey());
} else if (message instanceOf RouteToChild) {
    children.get(message.getKey()).forward(message, getContext());
} else if (message instanceOf Terminated) {
    staleActorRefs.remove(message.actor().path().name());
}

此递归消息传递意味着您的主管将不断尝试添加,直到终止完成。

如果在ActorRef陈旧时RouteToChild到达,则会出现问题,但该情况的解决方案是开放式的,并且未在问题中指定...

不要这样做

说了这么多,我同意问题中的引用:“这不是好习惯”。

与UUID一起去,让自己避免头痛......