Akka监控《eighteen》译

本章概述了监管背后的概念,并提供一些语义的说明。描述如何将其转换为实际代码的详细信息,请参阅Scala和Java API的相应章节。html

示例项目:你能够看到在实践中如何使用akka-samples-supervision-javajava

监控手段

如Actor Systems监管中所述,描述了Actor之间的依赖关系:主管将任务委托给下属,所以必须回应他们的失败。当下属检测到故障(即抛出异常)时,它会暂停自身及其全部下属,并向其主管发送消息,指示故障。根据要监督的工做性质和失败的性质,主管能够选择如下四种选择:编程

  1. 恢复下属,保持其累积的内部状态重启下属
  2. 重启下属,清除其累积的内部状态
  3. 永久中止下属
  4. 升级失败,从而自身失败

重要的是始终将一个Actor视为监督层级的一部分,这解释了第四个选择的存在(做为一个主管也从属于另外一个上级的主管)而且对前三个有影响:恢复一个Actor恢复它的所有下属,从新启动一个actor须要从新启动它的全部下属(可是请参阅下面的更多细节),相似地终止一个actor也将终止它的全部下属。须要注意的是,Actor类的preRestart的默认行为是在从新启动以前终止其全部子节点,可是能够重写此此方法;递归重启适用于执行此hook后留下的全部子节点。函数

每一个主管配置有一个功能,将全部可能的故障缘由(如:exceptions)转换为上面给出的四个选择之一;值得注意的是,此函数不会将失败的actor的身份做为输入。很容易想出结构的例子,这可能看起来不够灵活,例如:但愿将不一样的策略应用于不一样的下属。在这一点上,理解监督是关于造成递归故障处理结构是相当重要的。若是你试图在一个层面作太多,那将很难推理,所以在这种状况下推荐的方法是增长必定程度的监督。post

Akka实施了一种称为“parental supervisio(父母监督)”的特定形式。Actor只能由其余Actor建立 - 其中顶级Actor由library提供 - 每一个建立的Actor都由其父级监督。这种限制使得Actor监督等级的造成是隐含的,并鼓励合理的设计决策。应该指出的是,这也保证了Actor不能从外部成为孤儿或附属于监督者,不然可能会让他们不知不觉。此外,这为actor应用程序的(子树)产生了一个天然而干净的关闭过程。spa

Actor系统将在其建立过程当中启动至少三个Actor,如上图所示。有关actor路径的后果的更多信息,请参阅Actor路径的Top-Level Scopes for Actor Paths.设计

/user: The Guardian Actor

可能与之交互最多的Actor是全部用户建立的演员的父母,监护人名为“/ user”。使用system.actorOf()建立的Actor是此actor的子级。这意味着当该监护人终止时,系统中的全部经常使用Actor也将被关闭。这也意味着这个监护人的监督策略决定了顶级Actor的监督方式。从Akka 2.1开始,可使用设置akka.actor.guardian-supervisor-strategy来配置它,该策略采用SupervisorStrategyConfigurator的彻底限定类名。当监护人升级失败时,根监护人的回应将是终止监护人,这实际上将关闭整个Actor系统。htm

/system: The System Guardian

这个特殊的监护人被引入,以实现有序的关闭序列,其中记录保持活动,而全部正常的Actor终止,即便记录自己是使用actor实现的。这是经过让系统监护人观察用户监护人并在接收到终止消息时启动其本身的关闭来实现的。顶级系统actor使用策略进行监督,该策略将在全部类型的Exception上无限期地从新启动,除了ActorInitializationException和ActorKilledException,它将终止有问题的子节点。全部其余throwables都会升级,这将关闭整个actor系统。blog

/: The Root Guardian

root guardian是全部所谓的“顶级”Actor的祖母,并使用SupervisorStrategy.stoppingStrategy监督路径的顶级范围中提到的全部特殊Actor,其目的是终止任何类型的孩子异常。因为每一个真正的Actor都有一个主管,root guardian的主管不能成为真正的Actor。并且由于这意味着它“在泡沫以外”,它被称为“bubble-walker”。这是一个合成的ActorRef,它实际上会在遇到麻烦的第一个迹象时阻止其子进程,并在根守护者彻底终止(全部子进程递归中止)后当即将actor系统的isTerminated状态设置为true。递归

重启意味着什么

当呈如今处理特定消息时失败的Actor时,失败的缘由分为三类:

  • 收到的特殊消息的系统(即编程)错误
  • 处理消息期间使用的某些外部资源的(瞬态)故障
  • Actor内部错误

除非失败是可识别的,不然不能排除第三个缘由,这致使得出内部状态须要被清除的结论。若是主管决定其余孩子或其自己不受失败影响有意识地应用了错误内核模式 - 所以最好重启子进程。这是经过建立基础Actor类的新实例并用子项的ActorRef中的新实例替换失败的实例来实现的;执行此操做的能力是将actor封装在特殊引用中的缘由之一。而后,新的actor继续处理其邮箱,这意味着从新启动在actor自己以外是不可见的,可是没有从新处理发生故障的消息。

重启期间的事件顺序以下:

  1. 暂停actor(这意味着它将不会处理正常的消息,直到恢复),并递归挂起全部子节点。
  2. 调用旧实例的preRestart hook(默认为向全部子节点发送终止请求并调用postStop)。
  3. 在preRestart期间等待全部被请求终止的子节点(使用context.stop())实际终止;这就像全部演员操做同样 - 是非阻塞的,来自最后一个被杀害的孩子的终止通知将影响到下一步的进展。
  4. 经过再次调用最初提供的工厂来建立新的actor实例。
  5. 在新实例上调用postRestart(默认状况下也调用preStart)。
  6. 向步骤3中未被杀死的全部子项发送重启请求;从新启动的子项将从步骤2递归地执行相同的过程。
  7. 恢复Actor。

生命周期监控意味着什么

与上述父项和子项之间的特殊关系相反,每一个Actor均可以监视任何其余Actor。因为Actor从创做中彻底活跃起来而且在受影响的主管以外看不到重启,惟一可用于监控的状态变化是从活着过渡到死亡。所以,监控用于将一个Actor与另外一个Actor联系起来,以便它能够对另外一个Actor的终止做出反应,这与对失败做出反应的监督相反。

生命周期监视是使用监视actor接收的Terminated消息实现的,其中默认行为是在没有另外处理的状况下抛出特殊的DeathPactException。要开始侦听Terminated消息,请调用ActorContext.watch(targetActorRef)。要中止侦听,请调用ActorContext.unwatch(targetActorRef)。一个重要的特性是不管监视请求和目标终止发生的顺序如何,都将传递消息,即,即便在注册时目标已经死亡,您仍然会收到消息。

若是主管不能从新启动其子女而且必须终止它们,监控特别有用,例如:若是在actor初始化期间出错。在这种状况下,它应该监视这些孩子并从新建立它们或安排本身稍后重试。

另外一个常见的用例是,在没有外部资源的状况下,Actor须要失败,外部资源也多是其本身的孩子之一。若是第三方经过system.stop(子)方法终止子项或发送PoisonPill,则主管可能会受到影响。

原文地址:https://doc.akka.io/docs/akka/2.5/general/supervision.html

相关文章
相关标签/搜索