简体   繁体   English

在Akka安排儿童演员

[英]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的新手,我想知道我应该如何处理将工作委托给其他(儿童)演员的演员,但是在哪里:

  1. Some of these child actors must be engaged in a particular order; 其中一些儿童演员必须按照特定的顺序参与; and
  2. Some of these child actors can be engaged in any order and can truly execute asynchronously to what the main/parent actor is doing 这些子演员中的一些可以以任何顺序参与,并且可以真正地与主要/父演员的动作异步执行

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才能继续参与或调用ActorBActorCActorD
  • 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 可以异步/并行地相互调用ActorBActorC ,但是MasterParent必须等待两者的响应,然后才能继续进行并调用/调用ActorD

In other words, when a ProcessData message is received by MasterParent : 换句话说,当MasterParent接收到ProcessData消息时:

  1. Run ActorA and wait for it to return a result; 运行ActorA并等待其返回结果; then 然后
  2. Run both ActorB and ActorC and wait for results from both of them; 同时运行ActorBActorC并等待它们的结果; then 然后
  3. Run 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM