Skip to content
gqlxj1987's Blog
Go back

Akka Monitor

Edit page

原文链接

对比起我们习惯的行令式(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的策略配置

生命周期

preStart

preStop

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

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模式体现了。


Edit page
Share this post on:

Previous Post
Akka Persistence
Next Post
Centralized logging in K8s