gpt4 book ai didi

java - 创建一个 ActorSelection 以获取在父 actor 中创建的 ActorRef

转载 作者:行者123 更新时间:2023-11-30 06:20:48 25 4
gpt4 key购买 nike

我有一个带有 ParentOrderActor 的 Akka 系统,它接收 CreateRead 消息以创建和读取子级 OrderActor分别。

如果我在 main "/user/..." 路径中创建所有 Actor,一切顺利:

// Inside the ParentOrderActor ("/user/orders")

// Create in "/user"
getContext().system().actorOf(new Props(OrderActor.class), "ABC");

// Read via an ActorSelection
ActorSelection actorSelection = getContext().system().actorSelection("/user/ABC");

当一切顺利时,日志会显示:

ParentOrderActor -> created: Actor[akka://system/user/ABC#1132819541]
ParentOrderActor -> received: Message[name=Read, id=ABC]
ParentOrderActor -> actorSelection: ActorSelection[Actor[akka://system/]/user/ABC]
ParentOrderActor -> for id=Message[name=Read, id=ABC], we retrieved ActorRef: Actor[akka://system/user/ABC#1132819541]

但是当尝试在 ParentOrderActor 中创建和读取子 actor 时:

// Inside the ParentOrderActor ("/user/orders")

// Create in "/user/orders"
getContext().actorOf(new Props(OrderActor.class), "ABC");

// Read via an ActorSelection
ActorSelection actorSelection = getContext().actorSelection("ABC");

正在打印:

ParentOrderActor -> created: Actor[akka://system/user/orders/$a/ABC#-436492577]
ParentOrderActor -> received: Message[name=Read, id=ABC]
ParentOrderActor -> actorSelection: ActorSelection[Actor[akka://system/user/orders/$a#478613574]/ABC]
Oops: java.util.concurrent.TimeoutException: Futures timed out after [2 seconds]
ParentOrderActor -> for id=Message[name=Read, id=ABC], we retrieved ActorRef: null

我已经在 actorSelection(...) 中尝试了所有类型的路径,但 ActorRef 始终为 null

为了完整起见,这里有一个简短的 SSCCE 来演示上述内容:

public class Main {

private static boolean createChildrenInUser = false;
private static LoggingAdapter log;

static abstract class Message {

final String id;

Message(String id) {
this.id = id;
}

@Override
public String toString() {
return "Message[name=" + getClass().getSimpleName() + ", id=" + id + "]";
}
}

static class Create extends Message {
Create(String id) {
super(id);
}
}

static class Read extends Message {
Read(String id) {
super(id);
}
}

static class ParentOrderActor extends UntypedActor {

@Override
public void preStart() {
log.debug("ParentOrderActor -> starting...");
}

@Override
public void onReceive(Object message) throws Exception {

log.debug("ParentOrderActor -> received: {}", message);

if(message instanceof Create) {
if(createChildrenInUser) {
// Create an Actor in the root context ("/user/id").
ActorRef created = getContext().system().actorOf(new Props(OrderActor.class), ((Create)message).id);
log.debug("ParentOrderActor -> created: {}", created);
}
else {
// Create an Actor in this ParentOrderActor's context ("/user/orders/id")
ActorRef created = getContext().actorOf(new Props(OrderActor.class), ((Create)message).id);
log.debug("ParentOrderActor -> created: {}", created);
}
}
else if(message instanceof Read) {
ActorRef ref = select((Message)message);
log.debug("ParentOrderActor -> for id={}, we retrieved ActorRef: {}", message, ref);
getContext().system().shutdown();
}
else {
unhandled(message);
}
}

private ActorRef select(Message message) {
try {
ActorSelection actorSelection;
if(createChildrenInUser) {
// Select the Actor with a certain id in the root context ("/user/id").
actorSelection = getContext().system().actorSelection("/user/" + message.id);
}
else {
// Create an Actor in this ParentOrderActor's context ("/user/orders/id")
actorSelection = getContext().actorSelection(message.id);
}
log.debug("ParentOrderActor -> actorSelection: {}", actorSelection);
Timeout timeout = new Timeout(2, TimeUnit.SECONDS);
AskableActorSelection askableActorSelection = new AskableActorSelection(actorSelection);
Future<Object> future = askableActorSelection.ask(new Identify(1), timeout);
ActorIdentity actorIdentity = (ActorIdentity) Await.result(future, timeout.duration());
return actorIdentity.getRef();
}
catch(Exception e) {
log.debug("Oops: {}", e);
return null;
}
}
}

static class OrderActor extends UntypedActor {

@Override
public void preStart() {
log.debug("OrderActor -> starting...");
}

@Override
public void onReceive(Object message) throws Exception {
log.debug("OrderActor -> received: {}", message);
unhandled(message);
}
}

public static void main(String[] args) {

ActorSystem system = ActorSystem.create("system");

log = Logging.getLogger(system, Main.class);

ActorRef orders = system.actorOf(new Props(ParentOrderActor.class).withRouter(new RoundRobinRouter(1)), "orders");

orders.tell(new Create("ABC"), orders);

orders.tell(new Read("ABC"), orders);
}
}

运行上面的代码将导致 Read 返回一个 ActorRef,它是 null。将 boolean 标志 createChildrenInUser 更改为 true 将在 "/user" 中创建子 actor,一切顺利。

问题:如何创建 ActorSelection 并获取在 /user/orders 中创建的 actor 的 ActorRef (ParentOrderActor)?

最佳答案

如果我正确理解你的问题并且你想要从父 actor 中加载子 actor 的最佳方式,那么你可以使用:

getContext().child("ABC")

这将返回一个 scala.Option<ActorRef>虽然不是 ActorSelection , 所以如果你想用通配符查找多个 child 并向他们发送一条消息,这种方法将不起作用。

关于java - 创建一个 ActorSelection 以获取在父 actor 中创建的 ActorRef,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21313519/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com