DevilKing's blog

冷灯看剑,剑上几分功名?炉香无需计苍生,纵一穿烟逝,万丈云埋,孤阳还照古陵

0%

Akka Monitor

原文链接

对比起我们习惯的行令式(imperative)编程模式,Actor编程模式更接近现实中的应用场景和功能测试模式。这是因为Actor是靠消息来驱动的,每种消息代表一项功能的运算指令

由于每个Actor的运算都在自己独立的线程里进行,所以我们不必担心Actor函数在运行中的交叉调用问题。Akka程序本就是一种原生的多线程程序,每个Actor都在一个自己的线程内独立运算它的receive函数

关于actor自有线程的实现?

在Akka编程里我们可以把每段可能产生异常的代码放到一个独立的Actor中去运算

父级Actor对发生异常的子级Actor有以下几种处理方式:

1、恢复运算(Resume):不必理会异常,保留当前状态,跳过当前异常消息,照常继续处理其它消息

2、重新启动(Restart):清除当前状态,保留邮箱及内容,终止当前Actor,再重新构建一个新的Actor实例,沿用原来的消息地址ActorRef继续工作

3、彻底终止(Stop):销毁当前Actor及ActorRef邮箱,把所有消息导向DeadLetter队列。

4、向上提交(Esculate):如果父级无法处理子级异常,则这种情况也视为父级出现的异常。按照规定,父级会将自己和子级Actor运算暂停挂起并把子级Actor实际产生的异常当作自己发生的异常提交给上一层父级处理(也就是说异常信息的发送者sender变成了父级Actor)

Akka处理异常的方式简单直接:如果发生异常就先暂停挂起然后交给直属父级Actor去处理。这就把异常封闭在这个Actor的监管链条里。Akka系统的监管链条实际代表一个功能的分散封闭运算,所以一个监管链条里发生的异常不会影响其它监管链条。换句话说就是Actor发生异常是封闭在它所属的功能内部的,一个功能发生异常不会影响其它功能。

Akka提供了OneForOneStrategy和AllForOneStrategy两种对待异常Actor的策略配置

  • OneForOneStrategy:只针对发生异常的Actor施用策略

  • AllForOneStrategy:虽然一个直属子级Actor发生了异常,监管父级Actor把它当作所有下属子级同时发生了相同异常,对所有子级Actor施用策略

生命周期

preStart

preStop

Akka提供了一种逐步延时重启策略(BackoffSupervisor)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
val childProps = Props(classOf[EchoActor])

val supervisor = BackoffSupervisor.props(
Backoff.onFailure(
childProps,
childName = "myEcho",
minBackoff = 3.seconds,
maxBackoff = 30.seconds,
randomFactor = 0.2 // adds 20% "noise" to vary the intervals slightly
).withManualReset
.withSupervisorStrategy(
OneforOneStrategy(){
case _: GivingUpException => Stop
case _: RetryableException => Restart
case _: MinorException => Resume
}
)
)

system.actorOf(supervisor, name = "echoSupervisor")

Akka提供了context.watch和context.unwatch来设置通过ActorRef对任何Actor的终止状态监视,无须父子级别关系要求。但是还是要求当前为actor?

生命周期监控函数中只有postStop被调用过,preRestart和postRestart都没引用。如果这样的话BackoffSupervisor就是一锤子买卖,是正真的let it crash模式体现了。