Akka 在容错方面有如下特点:
Akka 对于错误的观点值得称道:没有银弹,应该着眼于如何进行灾后重建
和传统应用将业务逻辑 和 try {} catch{} 错误处理绞在一起不同,Akka 的容错恢复是独立于业务逻辑的:Actors专注于自己的消息处理逻辑,而错误处理和策略设定,则由层 级结构里,它的监督者(父级Actor结点)来操心。
监督者(Supervisor)并不去catch子结点的错误,而是仅决策子结点该如何恢复:
在一个策略中,应对子结点错误,我们有四个选项进行响应:
系统内置了两种策略:
我们也可以自定义结点的策略: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")
}