转载

Akka in action: Let it crash

Akka 在容错方面有如下特点:

  • 分区容错(local & remote),错误隔离
  • Actors 基于策略进行监督和恢复
  • 在错误解决前,失效的Actor 可被挂起,转由系统代收消息(Dead Letter),并在恢复时继续之前的消息处理

Akka 对于错误的观点值得称道:没有银弹,应该着眼于如何进行灾后重建

Let it crash

和传统应用将业务逻辑 和 try {} catch{} 错误处理绞在一起不同,Akka 的容错恢复是独立于业务逻辑的:Actors专注于自己的消息处理逻辑,而错误处理和策略设定,则由层 级结构里,它的监督者(父级Actor结点)来操心。

Akka in action: Let it crash

监督者(Supervisor)并不去catch子结点的错误,而是仅决策子结点该如何恢复:

恢复策略

在一个策略中,应对子结点错误,我们有四个选项进行响应:

  • 重启 :actor将被ActorSystem用Props重新创建,新的actor实例在重启完成后,会继续处理出错前的消息——Akka中各actor进行通信是基于引用( ActorRef ,由ActorSystem维护),所以在重启后它会自动接收到未处理的消息
  • 继续 :忽略错误
  • 终止 :actor下线,不再继续处理消息
  • 提升 :监督者不知道怎么处理错误,向上级抛(如果是顶级结点,系统崩溃

系统内置了两种策略:

  • defaultStrategy :默认的策略响应将会应用到所有子结点上
  • stoppingStrategy :出错的结点将会被终止

我们也可以自定义结点的策略:OneForOneStrategy 是仅响应出错结点的策略,AllForOneStrategy 策略则是响应影响所有的子结点。

实例

在一个Actor系统中,Supervisor收到 spawn 消息就创建Worker子结点,当这些Worker遇到不同的错误时,Supervisor 将使用一对一策略进行不同的响应:

import scala.concurrent.duration._
import akka.actor.{Actor, ActorLogging, ActorSystem, OneForOneStrategy, Props}
import akka.actor.SupervisorStrategy._
 
class Supervisor extends Actor with ActorLogging {
  override def receive: Receive = {
    case "spawn" => context.actorOf(Props[Worker])
  }
 
  override val supervisorStrategy =
    OneForOneStrategy(maxNrOfRetries = 10, withinTimeRange = 30 seconds) {
      case _: ArithmeticException      => Resume
      case _: NullPointerException    => Restart
      case _: IllegalArgumentException => Stop
      case _: Exception                => Escalate
    }
}
 
class Worker extends Actor with ActorLogging {
  override def receive: Receive = ???
}
 
object StrategyApp extends App {
  implicit val system = ActorSystem("actor-system")
  import system.dispatcher
 
  system.actorOf(Props[Supervisor], "supervisor")
}
原文  http://www.moye.me/2016/08/21/akka-in-action_let-it-crash/
正文到此结束
Loading...