Akka를 살펴보고 있는데 아래의 Props방식에서 new 연산자로 객체를 만들어서 만드는 방식을 금하고 있었다.
// NOT RECOMMENDED within another actor:
// encourages to close over enclosing class
val props7 = Props(new MyActor)
- 이 방식은 다른 Actor 내부에서 사용하는 것을 권장하지 않는다.
- 이유는 Props 객체가 직렬화가 불가능
- Actor의 캡슐화 원칙이 깨질수 있음.
예를 들어서 아래의 소스에서 new MyActor를 인자로 넣었다고 했을 때
class ParentActor extends Actor {
val someState = "important info"
def receive = {
case "spawn" =>
val props7 = Props(new MyActor)
val child = context.actorOf(props7)
}
}
MyActor Class에서 외부 클래스인 ParentActor의 정보를 접근하는 코드가 있다고 하면?
class MyActor extends Actor {
override def preStart(): Unit = {
println(ParentActor.this.someState) // 외부 스코프 접근!
}
}
- 직렬화(serialize)가 어려워짐
- Actor의 독립성/캡슐화 원칙이 깨짐
- Actor는 내 상태는 나만 관리한다가 원칙!
- 멀티쓰레드 환경에서 race condition이 발생할 수 있음.
- 다른 Actor의 상태를 동시에 참조/변경 가능
Q) 그러면 new MyActor()에서 인자를 넣어서 처리하면 MyActor Class안에서
외부 ParentActor 클래스의 내용을 접근하는 소스가 없도록하면 되는거 아닌가?
ParentActor의 상태(name)는 MyActor 생성자 인자로 명시적으로 넘겨줌.
MyActor 내부에서도 외부 ParentActor의 멤버들에 접근하지 않음!
즉, 외부 스코프 캡처가 일어나지 않음! 이건 해결했으나..
class ParentActor extends Actor {
val name = "태하팍"
def receive = {
case "spawn" =>
val props = Props(new MyActor(name)) // 외부 상태 name을 안전하게 넘김
context.actorOf(props)
}
}
class MyActor(name: String) extends Actor {
def receive = {
case _ => println(s"Hello $name")
}
}
Akka 클러스터 같은 분산환경에서 사용되는 Props는 직렬화가 당연히 가능해야함.
Actor를 다른 JVM node에 생성하려면 네트워크로 보내야 함(직렬화)
그런데 직렬화 불가능! Why???
val props = Props(new MyActor("태하팍"))
new MyActor("태하팍") 이 부분은 new를 써서 Actor 객체를 직접 생성하고 그걸 Props에 넣어 줌.
객체이기 때문에 heap영역에 생성을 하며 해당 객체에는 숨겨진 참조들이 있을 수 있음.
(자신을 생성한 클래스, 외부 클래스의 변수, 익명함수 등등)
이런 JVM 내부참조되는 객체들이 직렬화가 불가능한 상태일 수 있음.
특히 ParentActor는 Serializable(직렬화)를 할 수 없습니다.
Q. 그럼 Serializable하게 아래처럼 만들어준다면? 가능??
class ParentActor extends Actor with Serializable {
val name = "태하팍"
def receive = {
case "spawn" =>
val props = Props(new MyActor(name))
context.actorOf(props)
}
}
class MyActor(name: String) extends Actor {
def receive = {
case _ => println(s"Hello $name")
}
}
불가능! ParentActor는 해결될지 모르나 Actor Class 자체가 이미 직렬화 불가능한 필드를 가지고 있음.
context, scheduler, system 등등 -> Akka 내부 객체들이며 자체적으로 만든거라 제어 불가능!
결론
우회하려고 하지말고 권장하는 방식으로 사용하랏!
즉, Props(classOf[Actor], args...) + companion object에 팩토리 메서드 정의하랏!
끝~
'Data Platform > Akka' 카테고리의 다른 글
Akka Classic 뽀개기_Overview (0) | 2025.03.26 |
---|---|
Akka Classic (0) | 2025.03.25 |
Akka HelloWorld (0) | 2025.03.24 |