监控生命周期
actor的生命周期可以监控。 当actor终止,生命周期随之结束。 当supervisor决定停止actor,或者调用了stop方法,或者收到PoisonPill消息导致stop方法被间接调用,actor终止。 由于preRestart的默认实现是停止所有子actor,所以重启时,子actor会被终止。 在这种意义上,preRestart中崩溃的actor并没有终止。 它只是被从actor系统中移除,并没有直接或间接的用stop方法终止。 因为actor的引用在重启之后还要继续使用,actor的实例没有终止,只是被替换了。 ActorContext提供了watch方法来监控actor和unwatch方法来取消监控。 一旦一个actor调用watch方法来监控另外一个actor的引用,它就成为被监控actor的monitor。 当被监控的actor终止时,会给monitor发送终止消息。 终止消息只包含被终止actor的引用。 在重启中没有终止崩溃的actor是有道理的,否则你会收到很多崩溃消息,你很难区分是真正的终止还是重启。 下面的例子显示了DbWatcher监控dbWriter的生命周期。
Listing 4.8
class DbWatcher(dbWriter: ActorRef) extends Actor with ActorLogging {
context.watch(dbWriter) // 1
def receive = {
case Terminated(actorRef) => // 2
log.warning("Actor {} terminated", actorRef) // 3
}
}
1. 监控dbWriter
2. 崩溃actor引用在消息中被发送过来
3. 记录日志:dbWriter已经崩溃
monitor不一定非要是supervisor,可以是任意一个actor。 只要这个actor有被监控actor的引用,就可以通过context.watch(actorRef)实现对actorRef的监控。 当被监控actor终止时,monitor就可以收到终止消息。 monitor和supervisor可以是一个,而且很强大,下一节我们会看到。
我们还没有讨论supervisor如何决定actor的命运,子actor应该被终止、重启还是停止。 这是下一节的主要议题:监管。 下一节我们首先看看管理层级是怎么建立起来的,然后再看看supervisor可以使用的策略。