관리 메뉴

HAMA 블로그

예제로 보는 아카(akka) - 3. 부모,자식 액터 본문

Akka

예제로 보는 아카(akka) - 3. 부모,자식 액터

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

- Scala 2.11 기반 

- Akka 2.4.11 기반 

Learning Concurrent Programming in Scala 참고 


부모 액터 

class ParentActor extends Actor {
val log = Logging(context.system, this)
def receive = {
case "create" =>
context.actorOf(Props[ChildActor])
log.info(s"created a new child - children = ${context.children}")
case "hi" =>
log.info("Kids, say hi!")
for (c <- context.children) c ! "hi"
case "stop" =>
log.info("parent stopping")
context.stop(self)
}
}

- "create" 메세지를 받고 자식 액터를 생성.  context 를 이용한다. 
- "hi" 를 받으면 자식 액터들에게 "hi" 를 전달. context 에 자식들의 참조가 있다. 
- "stop" 을 받으면 부모 액터 종료. 부모액터가 종료되면 자동적으로 모든 자식들도 종료된다.

자식 액터 

class ChildActor extends Actor {
val log = Logging(context.system, this)
def receive = {
case "hi" =>
val parent = context.parent
log.info(s"my parent $parent made me say hi!")
}
override def postStop() {
log.info("child stopped!")
}
}

- "hi" 메세지 받으면 context 에서 부모참조를 찾아서 부모이름을 출력
- postStop 메소드를 오버라이드한다. 이것은 액터가 종료되기전에 호출된다. 

프로젝트 시작 

object ActorsHierarchy extends App {
// 액터 시스템 생성 . 이름은 mysystem
val ourSystem = ActorSystem("mysystem")

val parent = ourSystem.actorOf(Props[ParentActor], "parent")
parent ! "create"
parent ! "create"
Thread.sleep(1000)
parent ! "hi"
Thread.sleep(1000)
parent ! "stop"
Thread.sleep(1000)
ourSystem.terminate()

}

- 액터 시스템을 생성하고 부모 액터를 만든다.
- 부모 액터에게 자식을 생성하라는 메세지를 2번 보낸다.
- hi" 라는 메세지 보낸 후에 stop 을 호출해서 종료 시킨다.

결과

created a new child - children = ChildrenContainer(Actor[akka://mysystem/user/parent/$a#-732427736])
created a new child - children = ChildrenContainer(Actor[akka://mysystem/user/parent/$a#-732427736], Actor[akka://mysystem/user/parent/$b#-1467998879])
Kids, say hi!
my parent Actor[akka://mysystem/user/parent#1509478128] made me say hi!
my parent Actor[akka://mysystem/user/parent#1509478128] made me say hi!
parent stopping
child stopped!
child stopped!

부모/자식 관계도

-  부모와 이름 없는 자식 2개가 액터 시스템 하위에 있다.
-  user 액터는 애플리케이션에서 사용자가 만든 모든 액터의 최상위 액터이다. 
-  system 액터는 액터 시스템 내부적으로 사용하는 액터들의 부모이다. 


액터 식별

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

class CheckActor extends Actor {
import akka.actor.{Identify, ActorIdentity}
val log = Logging(context.system, this)
def receive = {
case path: String =>
log.info(s"checking path => $path")
context.actorSelection(path) ! Identify(path)
case ActorIdentity(path, Some(ref)) =>
log.info(s"found actor $ref on $path")
case ActorIdentity(path, None) =>
log.info(s"could not find an actor on $path")
}
}


object ActorsIdentify extends App {
val ourSystem = ActorSystem("mysystem")

val checker = ourSystem.actorOf(Props[CheckActor], "checker")
checker ! "../*"
Thread.sleep(1000)
checker ! "../../*"
Thread.sleep(1000)
checker ! "/system/*"
Thread.sleep(1000)
checker ! "/user/checker2"
Thread.sleep(1000)
checker ! "akka://OurExampleSystem/system"
Thread.sleep(1000)
ourSystem.stop(checker)
Thread.sleep(1000)
ourSystem.terminate()
}

설명

-  파일 시스템의 파일 경로와 매우 비슷하다.
-  ../* 현재 액터와 모든 형제들을 의미한다. 
- 액터 경로만을 사용해 특정 액터에 메세지를 보낼 수 없다.(액터 참조와 다름)
- 액터 경로에 있는 액터 참조를 얻으려면 context 객체에 대해 actorSelection 메소드를 호출.
- 어떤 아카 액터가 Identify 메세지를 받으면, 자동으로 자신의 ActorRef가 들어 있는 ActorIdentify 메세지로응답한다. 
- 액터 선택이 가르키는 액터가 없다면, 아무 ActorRef 객체가 없는 ActorIdentify 메세지를 송신한 액터에 돌려준다. 송신한 액터는  case ActorIdentify(path,None) 으로 받게된다.


결과

checking path => ../*    (현재 액터 부모의 아래에 있는 모든 자식 액터는? 현재 액터 뿐이네요) 
found actor Actor[akka://mysystem/user/checker#2076072686] on ../*
checking path => ../../* (현재 액터 조부모의 아래에 있는 모든 자식 액터는? system,user 액터네요
found actor Actor[akka://mysystem/system] on ../../*
found actor Actor[akka://mysystem/user] on ../../*
checking path => /system/*  (system 액터의 모든 자식액터는? 3가지가 있군요.
found actor Actor[akka://mysystem/system/deadLetterListener#1972095133] on /system/*
found actor Actor[akka://mysystem/system/log1-Logging$DefaultLogger#1684262536] on /system/*
found actor Actor[akka://mysystem/system/eventStreamUnsubscriber-1#228989081] on /system/*
checking path => /user/checker2 (user 액터 자식중 checker2 액터는?  없죠
could not find an actor on /user/checker2
checking path => akka://OurExampleSystem/system
could not find an actor on akka://OurExampleSystem/system


Comments