我创建了Master actor和child actor(使用Master中的router
创建)。
Master收到一些Job并将这份工作分成小任务并将它们发送给子actor(给路由者)。
我试图解决的问题是,当儿童演员完成工作时,我如何正确地通知我的主人?
在一些教程(Pi approximation和示例来自Scala In Action书中)主要演员收到儿童的回复后,试图将初始任务数组的大小与收到的结果大小进行比较:
if(receivedResultsFromChildren.size == initialTasks.size) {
// it's mean children finished their job
}
但我认为这是非常糟糕的,因为如果某个子actor抛出异常,那么它不会将结果发送回发送者(返回Master),因此这个条件永远不会评估为true
。
那么如何正确地通知大师所有孩子都完成了他们的工作?
我认为其中一个选项是Broadcast(PoisonPill)
给孩子,然后听Terminated(
路由器)
消息(使用所谓的deathWatch
)。可以解决吗?
如果使用Broadcast(PoisonPill)
更好,那么我是否应该注册一些监督策略,以便在发生异常时停止某些路由?因为如果发生异常,那么就像我所知,将重新启动routee,这意味着Master actor永远不会收到Terminated(
路由器)
。这是对的吗?
答案 0 :(得分:8)
在Akka,这实际上非常简单。
成功的孩子可以向父演员发送普通的回复消息。失败的参与者的意外失败可以在监督策略中被捕获并且被适当地处理(例如通过重新启动演员,或者通过停止它并将其从演员列表中移除来等待)。
所以看起来像这样:
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
}
}