[英]Orchestrating child actors in Akka
I am brand new to Akka and am wondering how I should be handling actors that delegate work out to other (child) actors, but where: 我是Akka的新手,我想知道我应该如何处理将工作委托给其他(儿童)演员的演员,但是在哪里:
Say I have the following child actors (doesn't matter what they do): 假设我有以下儿童演员(无论他们做什么):
// 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) {
…
}
}
And say I have the following parent actor that invokes them: 并说我有以下父级角色来调用它们:
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)
}
}
}
As you can see: 如你看到的:
ActorA
must be “ engaged ” (invoked by the parent) first, and we must wait for its response before MasterParent
can go ahead and engage/invoke ActorB
, ActorC
, or ActorD
. ActorA
必须首先“ 参与 ”(由父母调用),并且我们必须等待其响应,然后MasterParent
才能继续参与或调用ActorB
, ActorC
或ActorD
。 ActorB
and ActorC
can be invoked asynchronously/in parallel as one another, but then MasterParent
must wait for response from both before it can go ahead and engage/invoke ActorD
ActorB
和ActorC
,但是MasterParent
必须等待两者的响应,然后才能继续进行并调用/调用ActorD
In other words, when a ProcessData
message is received by MasterParent
: 换句话说,当
MasterParent
接收到ProcessData
消息时:
ActorA
and wait for it to return a result; ActorA
并等待其返回结果; then ActorB
and ActorC
and wait for results from both of them; ActorB
和ActorC
并等待它们的结果; then ActorD
ActorD
My main question is: How do I achieve this (Java pseudo-code or examples greatly appreciated!)? 我的主要问题是: 如何实现这一目标(Java伪代码或示例倍受赞赏!)?
Second, and arguable more importantly, since I'm so new to actors: Is this type of parent-child orchestration “normal” in Akka? 其次,更重要的是,因为我对演员还很陌生: 这种亲子编排在Akka中是否“正常”? Or, do Akka best practices typically dictate that all children run asynchronously and without imposed sequence/order/orchestration?
还是,Akka最佳实践是否通常会规定所有子代异步运行,而没有施加顺序/命令/编排?
First of all, yes since the MasterParent is delegating work to the other actors, it makes sense to have them as child actors. 首先,是的,因为MasterParent将工作委派给其他演员,所以将他们作为儿童演员是有意义的。
Also your idea of ResultOfA wasn't too far away from. 同样,您对ResultOfA的想法也相距不远。
This is one way you could do it: 这是您可以做到的一种方法:
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
}
}
Where every child actor would do sender().tell(resultX) so that the master receives the result. 每个子actor都将执行sender()。tell(resultX)的位置,以便主机可以接收结果。
ResultB and ResultC are both needed, so I save some state within the actor, which is set to null on every new instance of ProcessData, so it is not possible to send multiple ProcessData to one MasterParent in this case. ResultB和ResultC都需要,因此我在actor中保存了一些状态,该状态在ProcessData的每个新实例上都设置为null,因此在这种情况下无法将多个ProcessData发送到一个MasterParent。
If you want to send multiple ProcessData messages to one MasterParent without waiting, you would need to keep it free of state and therefore could employ the Ask Pattern on actorB and actorC and resolve the returning futures together. 如果您想不等待就将多个ProcessData消息发送到一个MasterParent,则需要使其保持无状态,因此可以在actorB和actorC上使用Ask Pattern并一起解析返回的期货。 So something like:
所以像这样:
Future futureA = actorB.ask(resultA)
Future futureB = actorC.ask(resultA)
And then compose them and register a callback where you send a request to actorD. 然后编写它们并注册一个回调,然后在其中向actorD发送请求。
This code pseudo codish, so not runnable. 此代码为伪编码,因此不可运行。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.