编排 child 个参与者
Orchestrating child actors in Akka
我是 Akka 的新手,想知道我应该如何处理将工作委托给其他 (child) 演员的演员,但是在哪里:
- 其中一些 child 参与者 必须 参与特定的订单;和
- 其中一些 child 参与者可以按任何顺序参与,并且可以真正异步执行 main/parent 参与者正在做的事情
假设我有以下 child 演员(不管他们做什么):
// Grovy pseudo code
class ActorA extends UntypedActor {
@Override
void onReceive(Object message) {
if(message instanceof RunActorA) {
…
}
}
class ActorB extends UntypedActor {
@Override
void onReceive(Object message) {
if(message instanceof RunActorB) {
…
}
}
class ActorC extends UntypedActor {
@Override
void onReceive(Object message) {
if(message instanceof RunActorC) {
…
}
}
class ActorD extends UntypedActor {
@Override
void onReceive(Object message) {
if(message instanceof RunActorD) {
…
}
}
并假设我有以下 parent 调用它们的演员:
class MasterParent extends UntypedActor {
ActorRef actorA
ActorRef actorB
ActorRef actorC
ActorRef actorD
MasterParent(ActorRef actorA, ActorRef actorA, ActorRef actorA, ActorRef actorA) {
super()
this.actorA = actorA
this.actorB = actorB
this.actorC = actorC
this.actorD = actorD
}
@Override
void onReceive(Object message) {
if(message instanceof ProcessData) {
ProcessData pData = message as ProcessData
Widget widget = pData.widget
RunActorA runA = new RunActorA(widget)
actorA.tell(runA, self)
// Somehow obtain a result from A, perhaps an “ResultOfA” object.
ResultOfA resultA = ??? // get from ActorA
RunActorB runB = new RunActorB(resultA)
RunActorC runC = new RunActorC(resultA)
actorB.tell(runB, self)
actorC.tell(runC, self)
// Somehow wait until both B and C return a result, say, ResultOfB and ResultOfC, respectively.
ResultOfB resultB = ??? // get from ActorB
ResultOfC resultC = ??? // get from ActorC
RunActorD runD = new RunActorD(resultB, resultC)
actorD.tell(runD, self)
}
}
}
如您所见:
ActorA
必须首先“engaged”(由 parent 调用),我们 必须 在 MasterParent
可以继续之前等待其响应,并且 engage/invoke ActorB
、ActorC
或 ActorD
.
ActorB
和 ActorC
可以彼此并行调用 asynchronously/in,但是 MasterParent
必须等待两者的响应才能继续并且 engage/invokeActorD
换句话说,当 ProcessData
消息被 MasterParent
接收到时:
- 运行
ActorA
然后等待return一个结果;然后
- 运行
ActorB
和 ActorC
并等待他们两个的结果;然后
- 运行
ActorD
我的主要问题是:我如何实现这一目标(Java pseudo-code 或示例 非常 赞赏!)?
其次,更重要的是有争议,因为我对演员很陌生:这种类型的 parent-child orchestration 在 Akka 中是“正常的”吗? 或者,做Akka 最佳实践通常规定所有 children 运行 异步且不强加 sequence/order/orchestration?
首先,是的,因为 MasterParent 正在将工作委派给其他演员,所以让他们作为子演员是有意义的。
另外,您对 ResultOfA 的想法也相差不远。
这是您可以做到的一种方式:
ResultOfB resultB = null;
ResultOfC resultC = null;
@Override
void onReceive(Object message) {
if(message instanceof ProcessData) {
ProcessData pData = message as ProcessData
resultB = null;
resultC = null;
Widget widget = pData.widget
RunActorA runA = new RunActorA(widget)
actorA.tell(runA, self)
} else if (message instanceof ResultOfA) {
ResultOfA resultA = message as ResultOfA
actorB.tell(resultA)
actorC.tell(resultA)
} else if (message instanceof ResultOfB) {
resultB = message as ResultOfB
if (resultC != null) {
actorD.tell(composedResultBAndC)
}
} else if (message instanceof ResultOfC) {
resultC = message as ResultOfC
if (resultB != null) {
actorD.tell(composedResultBAndC)
}
} else if (message instanceof ResultOfD) {
//Do stuff with the result
}
}
每个子 actor 都会执行 sender().tell(resultX) 以便 master 接收结果。
ResultB 和 ResultC 都是必需的,所以我在 actor 中保存了一些状态,在 ProcessData 的每个新实例上都设置为 null,因此在这种情况下不可能将多个 ProcessData 发送到一个 MasterParent。
如果您想在不等待的情况下向一个 MasterParent 发送多条 ProcessData 消息,您需要使其保持无状态,因此可以在 actorB 和 actorC 上使用 Ask Pattern 并一起解析返回的 futures。所以像:
Future futureA = actorB.ask(resultA)
Future futureB = actorC.ask(resultA)
然后 compose them 并注册一个回调,在其中向 actorD 发送请求。
这段代码伪代码,所以不可运行。
我是 Akka 的新手,想知道我应该如何处理将工作委托给其他 (child) 演员的演员,但是在哪里:
- 其中一些 child 参与者 必须 参与特定的订单;和
- 其中一些 child 参与者可以按任何顺序参与,并且可以真正异步执行 main/parent 参与者正在做的事情
假设我有以下 child 演员(不管他们做什么):
// Grovy pseudo code
class ActorA extends UntypedActor {
@Override
void onReceive(Object message) {
if(message instanceof RunActorA) {
…
}
}
class ActorB extends UntypedActor {
@Override
void onReceive(Object message) {
if(message instanceof RunActorB) {
…
}
}
class ActorC extends UntypedActor {
@Override
void onReceive(Object message) {
if(message instanceof RunActorC) {
…
}
}
class ActorD extends UntypedActor {
@Override
void onReceive(Object message) {
if(message instanceof RunActorD) {
…
}
}
并假设我有以下 parent 调用它们的演员:
class MasterParent extends UntypedActor {
ActorRef actorA
ActorRef actorB
ActorRef actorC
ActorRef actorD
MasterParent(ActorRef actorA, ActorRef actorA, ActorRef actorA, ActorRef actorA) {
super()
this.actorA = actorA
this.actorB = actorB
this.actorC = actorC
this.actorD = actorD
}
@Override
void onReceive(Object message) {
if(message instanceof ProcessData) {
ProcessData pData = message as ProcessData
Widget widget = pData.widget
RunActorA runA = new RunActorA(widget)
actorA.tell(runA, self)
// Somehow obtain a result from A, perhaps an “ResultOfA” object.
ResultOfA resultA = ??? // get from ActorA
RunActorB runB = new RunActorB(resultA)
RunActorC runC = new RunActorC(resultA)
actorB.tell(runB, self)
actorC.tell(runC, self)
// Somehow wait until both B and C return a result, say, ResultOfB and ResultOfC, respectively.
ResultOfB resultB = ??? // get from ActorB
ResultOfC resultC = ??? // get from ActorC
RunActorD runD = new RunActorD(resultB, resultC)
actorD.tell(runD, self)
}
}
}
如您所见:
ActorA
必须首先“engaged”(由 parent 调用),我们 必须 在MasterParent
可以继续之前等待其响应,并且 engage/invokeActorB
、ActorC
或ActorD
.ActorB
和ActorC
可以彼此并行调用 asynchronously/in,但是MasterParent
必须等待两者的响应才能继续并且 engage/invokeActorD
换句话说,当 ProcessData
消息被 MasterParent
接收到时:
- 运行
ActorA
然后等待return一个结果;然后 - 运行
ActorB
和ActorC
并等待他们两个的结果;然后 - 运行
ActorD
我的主要问题是:我如何实现这一目标(Java pseudo-code 或示例 非常 赞赏!)?
其次,更重要的是有争议,因为我对演员很陌生:这种类型的 parent-child orchestration 在 Akka 中是“正常的”吗? 或者,做Akka 最佳实践通常规定所有 children 运行 异步且不强加 sequence/order/orchestration?
首先,是的,因为 MasterParent 正在将工作委派给其他演员,所以让他们作为子演员是有意义的。
另外,您对 ResultOfA 的想法也相差不远。
这是您可以做到的一种方式:
ResultOfB resultB = null;
ResultOfC resultC = null;
@Override
void onReceive(Object message) {
if(message instanceof ProcessData) {
ProcessData pData = message as ProcessData
resultB = null;
resultC = null;
Widget widget = pData.widget
RunActorA runA = new RunActorA(widget)
actorA.tell(runA, self)
} else if (message instanceof ResultOfA) {
ResultOfA resultA = message as ResultOfA
actorB.tell(resultA)
actorC.tell(resultA)
} else if (message instanceof ResultOfB) {
resultB = message as ResultOfB
if (resultC != null) {
actorD.tell(composedResultBAndC)
}
} else if (message instanceof ResultOfC) {
resultC = message as ResultOfC
if (resultB != null) {
actorD.tell(composedResultBAndC)
}
} else if (message instanceof ResultOfD) {
//Do stuff with the result
}
}
每个子 actor 都会执行 sender().tell(resultX) 以便 master 接收结果。
ResultB 和 ResultC 都是必需的,所以我在 actor 中保存了一些状态,在 ProcessData 的每个新实例上都设置为 null,因此在这种情况下不可能将多个 ProcessData 发送到一个 MasterParent。
如果您想在不等待的情况下向一个 MasterParent 发送多条 ProcessData 消息,您需要使其保持无状态,因此可以在 actorB 和 actorC 上使用 Ask Pattern 并一起解析返回的 futures。所以像:
Future futureA = actorB.ask(resultA)
Future futureB = actorC.ask(resultA)
然后 compose them 并注册一个回调,在其中向 actorD 发送请求。
这段代码伪代码,所以不可运行。