Akka. 如何知道所有子级 Actor 已完成其工作

4
我创建了Master actor和child actors(使用router从Master创建)。Master接收一些Job并将其拆分成小任务,然后将它们发送给子actor(routees)。
我想要解决的问题是当child actors完成任务时如何正确地通知Master?
在一些教程(例如Pi approximation和Scala In Action书中的示例),Master actor在接收到子actor的响应后会比较任务的初始数组大小和接收到的结果大小。
if(receivedResultsFromChildren.size == initialTasks.size) {
    // it's mean children finished their job
}

但我认为这很糟糕,因为如果某个儿童演员抛出异常,那么它将不会将结果发送回发送方(回到Master),所以此条件永远不会评估为true

那么如何正确地通知主人所有孩子完成了他们的工作呢?

我认为其中一个选项是向孩子们广播PoisonPill,然后监听Terminated(router)消息(使用所谓的deathWatch)。这是一个好的解决方案吗?

如果使用Broadcast(PoisonPill)更好,那么我是否应该注册一些监督策略,在发生异常的情况下停止某些路由器?因为如果发生异常,那么路由器将被重启,我知道这意味着Master actor将永远不会收到Terminated(router)。这是正确的吗?


有一个所谓的聚合器模式 - jilen
1个回答

9
在Akka中,这实际上非常简单。
成功的子级可以向父级Actor发送普通的回复消息。失败的Actor的意外故障可以在监管策略中捕获并适当处理(例如通过重新启动Actor,或者通过停止它并将其从等待Actor列表中删除)。
因此,它可能看起来像这样:
var waitingFor = Set.empty[ActorRef]

override def preStart() = ??? // Start the children with their subtasks

override def supervisionStrategy = OneForOneStrategy() {
    case _ => {
       waitingFor -= sender()
       if (waitingFor.isEmpty) ??? // processing finished
       Stop
    }
}

override def receive = {
    case Reply => {
        waitingFor -= sender()
        if (waitingFor.isEmpty) ??? // processing finished
    }
}

1
这在一般情况下似乎是个好主意,即使对于工作演员而不是子演员也是如此。然而,我想解决一个稍微不同的问题:我想在所有子演员停止的时刻停止一个演员。这里最简单的解决方案是什么? - Nikola Schou

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接