관리 메뉴

HAMA 블로그

예제로 보는 아카(akka) - 12. 액터 찾기 & 참조하기 & 액터 패스 본문

Akka

예제로 보는 아카(akka) - 12. 액터 찾기 & 참조하기 & 액터 패스

[하마] 이승현 (wowlsh93@gmail.com) 2016. 10. 18. 18:31

- Scala 2.11.8 기반 

- Akka 2.4.11 기반 

- Java 8  (akka 2.4 부터는 java 8 요구함. scala 2.11 은 java 7도 괜찮지만~) 

- Akka 공식 문서 : http://doc.akka.io/docs/akka/snapshot/general/addressing.html



액터 찾기 & 참조하기

액터시스템에 여러개의 액터가 활동 할 때 , A 액터는 메세지에 따라서 B,C,D 액터에게 메세지를 따로 보내야 할때가 있다. 이때 A 액터는 B,C,D 액터에 대한 참조를 어떻게 알 수 있을까? 일단 보통 객체 코딩 했었을 때 를 생각하면서 A 액터에 setActor 같은 메소드를 만들어서 B,C,D  액터의 참조를 주입시키는 방법으로 손가락이 먼저 반응 했는데 다른 방법이 있다. 

val ruleEngine  = context.actorSelection("/user/RuleEngine")

이렇게 actorSelection 을 통해서 멤버로 가지고 있으면 된다. 이때 주의 할점은 /user 앞에 슬래쉬(/) 잊지말길.. 저거 때문에 한참 해맸다 ㅜㅜ 


그리고 액터의 라이프 사이클을 관리하는 차원에서 actor path 보다는 actor ref 를 이용하자. 
아래 내용에 나오겠지만 Identify() 를 이용하여 획득 할 수 있다. 


액터 식별 정리 


@ 최상위의 사용자 액터들은  /user/ 아래에 위치한다. 
@ /user/*  하면 최상위의 모든 액터로 가는 패스를 리턴 한다. 

@ ../* 는 현재 액터와 모든 형제들을 의미한다. 

@ actorSelection 은 ActorRef 대신 ActorSelection 객체를 반환한다. 0~여러개의 개수일 수 있으니..

@ 역터 시스템에 있는 임의의 액터들과 통신하기 위해서는 actorSelection 을 이용한다. 

@ actorSelection 은 실제 액터 참조를 알려 주진 않는다. 실제 액터 참조를 얻기 위해서는 Identify 메세지를       이용한다. 


액터 식별 예제 

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) 으로 받게된다.


Actor Path 형식 

  1. "akka://my-sys/user/service-a/worker1" // 지역 액터 패스
  2. "akka.tcp://my-sys@host.example.com:5678/user/service-b" // 원격 액터 패스


Actor Path 와 Actor Ref 와 차이점 


-  액터 참조는 액터가 실제 있어야 만들어진다. 반면 패스는 실제 액터가 없어도 만들 수 있다. 
-  A 액터를 만들고 종료시키고 B 액터를 만들었을때 , 동일한 액터패스를 가질 수 있다. 그냥 이름이니깐

   하지만 액터 참조는 그대로 사용 할 수 없다. 액터 참조는 대응되는 액터의 라이프 사이클과 함께 한다.


원격 Actor 의 Path

 -  로컬의 액터의 자식 액터를 만드는데 위치를 원격에 둘 수 있다.
   -  이때 로컬에서 보기에 자식패스로 볼 수 있지만 실제는 원격에 위치해있다. 바인딩된다.



언제 ActorSelection 를 써야 하나요?


참고:https://petabridge.com/blog/when-should-I-use-actor-selection/ 


1. 액터의 위치를 와일드 카드를 이용 하여 처리하는 방법이 필요 할때

2. 원격액터시스템의 액터와 커뮤니케이션 하고 싶을때, 그 액터에 대한 참조를 아직 가지고 있지 않았고


유의 사항 

* 가능하면 항상 ActorRef 를 사용하라. (액터가 죽었더라도 액터 패스는 메세지를 보낸다) 

   또한 ActorRef 를 사용하면 참조하는 액터들의 라이프 사이클을 알 수 있으니..

* 개별 액터코드내에 액터패스를 하드 코딩하지 말고 한곳에 모아둬라. (읽기전용 스태틱으로~) 




참고 : 아래 같은 방법으로 액터를 관리한다. 


val selection = context.actorSelection(
"akka.tcp://sys@10.0.0.1:2552/user/world")
selection ! Identify(None)
var ref: ActorRef = _
def receive = {
case ActorIdentity(_, Some(actorRef)) =>
ref = actorRef
context watch ref
case ActorIdentity(_, None) => // not alive
case Terminated(r) if r == ref => // ...
}


Comments