backend/Scala_Play_Akka

[Akka] Akka Document - Actor Architecture (3) - Failure handling

버리야 2018. 4. 24. 10:16
반응형

이 글은 원문 : https://doc.akka.io/docs/akka/current/guide/tutorial_1.html 글을 읽고 간략하게 정리한 내용입니다. (생략된 내용도 있습니다.)



Akka Version 2.5.12


Failure handling


부모와 자식은 라이프 사이클 전반에 걸쳐 연결된다. actor가 실패 할 때마다 (예외를 던지거나 처리되지 않은 예외가 receive에서 끊어지면) 일시적으로 일시 중단된다. 앞서 언급했듯이, 실패 정보는 부모에게 전달되며, 부모는 자식 actor에 의해 발생한 예외를 처리하는 방법을 결정합니다. 이런 식으로 부모는 자식을 감독하는 역할을 한다. 기본 수퍼바이저 전략은 자식을 중지했다가 다시 시작하는 것이다. 기본 전략을 변경하지 않으면 모든 실패로 인해 다시 시작된다.


간단한 실험에서 기본 전략을 관찰해 보자. 이전 클래스와 마찬가지로 아래 클래스를 프로젝트에 추가하자.

class SupervisingActor extends Actor {
  val child = context.actorOf(Props[SupervisedActor], "supervised-actor")

  override def receive: Receive = {
    case "failChild" ⇒ child ! "fail"
  }
}

class SupervisedActor extends Actor {
  override def preStart(): Unit = println("supervised actor started")
  override def postStop(): Unit = println("supervised actor stopped")

  override def receive: Receive = {
    case "fail" ⇒
      println("supervised actor fails now")
      throw new Exception("I failed!")
  }
}

그리고 실행을 해보자.

val supervisingActor = system.actorOf(Props[SupervisingActor], "supervising-actor")
supervisingActor ! "failChild"

그러면, 다음과 같은 오류를 볼 수 있을 것이다.

supervised actor started
supervised actor fails now
supervised actor stopped
supervised actor started
[ERROR] [03/29/2017 10:47:14.150] [testSystem-akka.actor.default-dispatcher-2] [akka://testSystem/user/supervising-actor/supervised-actor] I failed!
java.lang.Exception: I failed!
        at tutorial_1.SupervisedActor$$anonfun$receive$4.applyOrElse(ActorHierarchyExperiments.scala:57)
        at akka.actor.Actor$class.aroundReceive(Actor.scala:513)
        at tutorial_1.SupervisedActor.aroundReceive(ActorHierarchyExperiments.scala:47)
        at akka.actor.ActorCell.receiveMessage(ActorCell.scala:519)
        at akka.actor.ActorCell.invoke(ActorCell.scala:488)
        at akka.dispatch.Mailbox.processMailbox(Mailbox.scala:257)
        at akka.dispatch.Mailbox.run(Mailbox.scala:224)
        at akka.dispatch.Mailbox.exec(Mailbox.scala:234)
        at akka.dispatch.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:260)
        at akka.dispatch.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1339)
        at akka.dispatch.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1979)
        at akka.dispatch.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:107)


위의 결과로 실패 후 supervised actor가 멈추고 즉시 다시 시작되는 것을 볼 수 있다. 

또한 처리된 예외 (이 경우에는 테스트 예외)를 reporting하는 로그 항목이 표시된다. 


이 예제에서는 preStart() 및 postStop() hook을 사용했다. 

이 hook은 다시 시작할 때와 호출하기 전에 기본값으로 호출되므로 처음 시작되었는지 또는 다시 시작되었는지 actor와 내부를 구분할 수 없다. 

이것은 대개 옳은 일로, 재시작의 목적은 일반적으로 깨끗한 시작 단계를 의미하는 알려진 양호한 상태로 actor를 설정하는 것이다. 

preRestart () 및 postRestart () 메서드가 호출되며, 재정의하지 않으면 기본적으로 postStop() 및 preStart()에 위임한다. 

이러한 추가 메서드를 재정의하고 출력이 어떻게 변경되는지 확인할 수 있다.






반응형