관리 메뉴

HAMA 블로그

예제로 보는 아카(akka) - 4. 액터 생명 주기 본문

Akka

예제로 보는 아카(akka) - 4. 액터 생명 주기

[하마] 이승현 (wowlsh93@gmail.com) 2016. 10. 5. 17:46

- Scala 2.11 기반 

- Akka 2.4.11 기반 

Learning Concurrent Programming in Scala 참고 


액터 생명 주기  

import akka.actor.{Actor, ActorRef, ActorSystem, Props}
import akka.event.Logging

class LifecycleActor extends Actor {
val log = Logging(context.system, this)
var child: ActorRef = _
def receive = {
case num: Double => log.info(s"got a double - $num")
case num: Int => log.info(s"got an integer - $num")
case lst: List[_] => log.info(s"list - ${lst.head}, ...")
case txt: String => child ! txt     
}
override def preStart(): Unit = {
log.info("about to start")
child = context.actorOf(Props[StringPrinter], "kiddo")
}
override def preRestart(reason: Throwable, msg: Option[Any]): Unit = {
log.info(s"about to restart because of $reason, during message $msg")
super.preRestart(reason, msg)
}
override def postRestart(reason: Throwable): Unit = {
log.info(s"just restarted due to $reason")
super.postRestart(reason)
}
override def postStop() = log.info("just stopped")
}


class StringPrinter extends Actor {
val log = Logging(context.system, this)
def receive = {
case msg => log.info(s"child got message '$msg'")
}
override def preStart(): Unit = log.info(s"child about to start.")
override def postStop(): Unit = log.info(s"child just stopped.")
}


object ActorsLifecycle extends App {
val ourSystem = ActorSystem("mysystem")
val testy = ourSystem.actorOf(Props[LifecycleActor], "testy")
testy ! math.Pi
Thread.sleep(1000)
testy ! 7
Thread.sleep(1000)
testy ! "hi there!"
Thread.sleep(1000) testy ! List(1,2,3)

Thread.sleep(1000)
testy ! Nil
Thread.sleep(1000)
testy ! "sorry about that"
Thread.sleep(1000)
ourSystem.stop(testy)
Thread.sleep(1000)
ourSystem.terminate()
}

- LifecycleActor 액터가 시작 될 때, preStart 가 호출되었다.
LifecycleActor 액터가 자식 액터를 만들었기때문에 StringPrinter 도 preStart가 호출된다.

눈여겨 봐야할 부분은 LifecycelActor  액터에 Nil (빈List객체)을 보내서 예외를 만든 후에 어떻게 액터가
반응하는지를 봐야한다. 진행 순서는 

0. 먼저 LifecycleActor 에서 예외가 발생
1. LifecycleActor 의 preRestart 호출 
2. LifecycleActor 의 postStop 호출 
3. LifecycleActor 의 자식 액터의 postStop 호출 
4. LifecycleActor 는 postRestart 호출  
6. LifecycleActor 의  preStart 호출
7. LifecycleActor 의 자식 액터가 만들어지면서 preStart 호출 

여기서 눈여겨 볼것은 4번인데 
postRestart  는  Props 객체를 재사용해 새로운 액터객체생성해서 호출한다.
그 후에 예전 액터 객체가 사용하던 우편함에 새 액터 객체를 할당한다.

결과

about to start
child about to start.
got a double - 3.141592653589793
got an integer - 7
child got message 'hi there!'
list - 1, ...
head of empty list 
java.util.NoSuchElementException: head of empty list  // 예외 발생 !!!
about to restart because of java.util.NoSuchElementException   // LifecycleActor preRestart 호출 
just stopped  // LifecycleActor postStop 호출 
child just stopped.  // LifecycleActor 의 자식 액터의  postStop 호출 
just restarted due to java.util.NoSuchElementException:  // LifecycleActor 액터의 postRestart 호출
about to start  // 새로 생성된 LifecycleActor 액터의 preStart 호출 
child about to start. // 새로 생성된 LifecycleActor 액터의 postRestart 호출
child got message 'sorry about that'
child just stopped.
just stopped


흐름도

흐름도를 보고 생명 주기를  복습해보자
0. 액터 에서 예외 발생
1. 해당 액터의 preRestart 호출
2. 해당 액터의 postStop 호출 
3. Props 를 이용해서 새로운 액터 생성 
4. 새 액터의 postRestart 호출 
5. 이전 액터가 사용하던 우편함을 새 액터에 할당
7. 해당 액터의 preStart 호출 




Comments