代码之家  ›  专栏  ›  技术社区  ›  Achilleus

使用AKKA actors时正确的异常处理方法

  •  0
  • Achilleus  · 技术社区  · 5 年前

    我正试图通过使用主管在我的AKKA项目中进行适当的异常处理。只是想确定这是不是正确的接近事物的方式。 我有一个演员系统,它创建了4个独立的演员。假设我的演员中有一个达到了一个分贝。监管策略是正确的处理方式吗?

    object ExceptionHandlingSupervisor extends App{
      val actorSystem = ActorSystem("ExceptionHandlingActorSystem")
      val actor = actorSystem.actorOf(Props[SupervisorActor], "SupervisorActor")
      actor ! Start
    
      class SupervisorActor extends Actor {
        val dbActor = context.actorOf(Props[ChildActor],"ChildActor")
        override def receive: Receive = {
          case Start => dbActor ! HitDatabase("","")
        }
    
        override val supervisorStrategy = OneForOneStrategy(loggingEnabled = false){
          case ae:SQLException => println("Found an SQLException") //Add my logging logic here and error notification logic here
            Resume
    
          case _:Exception => println("Found an Exception")
            Restart
    
        }
    
      }
    
      class ChildActor extends Actor{
        override def receive: Receive = {
          case HitDatabase(user,pass) => dbFunction(user,pass)
        }
      }
    }
    

    上面的代码是采用这种方法的方法,还是应该使用传统的Try/Catch块:

    class DbActor extends Actor{
            override def receive: Receive = {
              case HitDatabase(user,pass) => 
        try{
                dbFunction(user,pass)
              }
                catch {
                  case ae:SQLException => println("Found an SQLException") //Add my logging logic here and error notification logic here
                }
    

    如果你能告诉我, 在这种情况下,为什么要选择主管方法而不是传统的异常处理方法? 除了执行恢复或重新启动之外,我们可以在管理策略中指定其他一些错误处理逻辑吗?

    1 回复  |  直到 5 年前
        1
  •  2
  •   Leo C    5 年前

    除非需要以非常精细的方式或不同的方式在单个参与者中处理异常,否则我将让内置的管理策略处理异常以及相应的参与者重新启动/终止等。它还具有更好的可读性,因为它具有故障处理逻辑的中心位置。

    我们能在管理策略中指定一些其他错误处理逻辑吗? 除了继续还是重新启动?

    还有其他故障处理操作,如 Stop , Escalate 在管理策略上。 停止 终止子演员并 逐步升级 向上升级到主管的家长。在返回 Directive 在每一个 case ,只要 decider 代码块符合 PartialFunction[Throwable, Directive] . 例如:

    override val supervisorStrategy =
      OneForOneStrategy(maxNrOfRetries = 10, withinTimeRange = 1 minute) {
        case e: ArithmeticException =>
          myLogActor ! s"ERROR: $e from $sender; Resuming."
          Resume
        case _: Exception =>
          myLogActor ! s"ERROR: unknown exception from $sender; Escalating."
          Escalate
      }
    

    作为旁注,如果你必须 try/catch 方法,考虑使用 Try 相反,如下所示:

    Try(dbFunction(user, pass)) match {
      case Success(res)             => // do something with `res`
      case Failure(e: SQLException) => // log `e`, etc
      case Failure(e)               => // other exceptions ...
    }