관리 메뉴

HAMA 블로그

액터 모델의 문제점 본문

Akka

액터 모델의 문제점

[하마] 이승현 (wowlsh93@gmail.com) 2016. 12. 2. 11:27


이번 포스트에서는 액터모형/Akka액터에 대해 비판적인 시각에 대한 글을 적어 본다. 모든 기술에는 항상 빛과 어둠이 따르는 법. 양쪽을 모두 바라봐야 그 물체가 3D 입체적으로 보이지 않겠은가. 아래의 블로그글을 번역하였으며 물론 이 글도 비판적으로 봐야한다. 


What’s Wrong with the Actor Model

https://jaksa.wordpress.com/2015/10/13/whats-wrong-with-the-actor-model/

수십 년 동안 존재 해 왔지만 액터 모델은 2000년대 중반부터 기지개를 켜기 시작했습니다. Carl Hewitt와 Henry Baker의 1977 년 "병렬 프로세스에서 통신하는 방법"에서 처음 소개되었습니다. 액터 모델의 대중화는 부분적으로 무어의 법칙이 약화 된 데 기인하는데요 즉  프로세서가 더 이상 빨라지지 않고 코어의 수는 늘어서 다중 코어를  적극적으로 사용하는 병렬 소프트웨어를 작성 해야 하니까요. 적어도 그렇게 보였습니다. 업계 최초로 얼랭 (Erlang)과 같은 기존의 언어들이 다시 눈에 띄기 시작되었고  최근에는 Akka 와 같은 새로운 구현이 인기를 얻기 시작했습니다.

어쨌든 이 액터 모델은 무엇일까요? 실제로는 매우 간단합니다. 몇 가지 추가 사항을 포함한 오래되었지만 휼륭한  메세지 패싱 패러다임입니다.  원본 논문을 읽을 수도 있겠지만 Wikipedia는 무엇인지에 대한 좋은 요약을 제공합니다.

액터는 그것이 수신하는 메세지에 대해 응답(책임)을 가지고 있는 계산 개체이며 , 동시적으로 수행할 수 있습니다. (역주: 간단히 기술적으로 보면  자신의 쓰레드와 큐를  가지고 있는 객체라고 생각하면 더 좋다. 쓰레드와 큐를 공유해서 더 효율적으로 만들기도 함)

* 다른 액터에게 유한개수의 메시지를 보낸다.
* 새로운 액터의 유한하게  생성
* 수신한 메시지에 대응되는 동작을 지정한다.

액터 모델은 악명 높게 어려운 병렬 프로그래밍의 세계를 단순화 하기 위한 것입니다. (역주: 이러한 동시성 모델은 액터뿐만아니라 STM 등 여러가지고 있습니다. 폴부처의 '7가지 동시성 모델' 참고)  이 세 가지 작업들은  동시에 수행될 수 있으며 액터 모델이 해결하려고하는 것들에 대해 다시 소개해 드릴 수 있으나, 내가 지금 이야기하고 싶은 문제는 아니며, 실제로 액터 내부에서 순차적 실행 모델을 사용함으로써 대부분의 프레임 워크에 의해 교묘하게 회피하고 있는 부분에 대해서 말 할 것입니다. (역주: 혹시 순차적 실행 도중 긴 러닝시간을 갖는 로직 사용에 의한 락을 말하는거라면 원래 그렇게 사용하면 안되며 다른 쓰레드로 이전 시켜야겠지요) 

훨씬 더 큰 문제는 마케팅으로 인한 액터 모델의 오해입니다. 액터는 고 가용성, 데드락 (deadlock) 솔루션으로 판매되기 때문에 안전한 분산 및 동시 성 어플리케이션으로 생각하기가 쉽습니다. 진실이 이것과는 멀리 있다는 것을 발견하기 위하여 간단한 dining philosophers  를 실행해보면 그만입니다. 액터 모델은 실제로 당신이 하는 일에 대해서  정말로 알아야하는 매우 강력하고 전문가 전용 모델입니다. 그것은 안전한 환경이 아니며 교착 상태를 작성하는 것이 쉽고 스파게티 코드가 될 가능성이 큽니다. 안전한 병행 및 결함 허용 프로그래밍 모델을 원하면 컨테이너 관리 트랜잭션(container managed transactions이있는 EJBs를 사용해야합니다.

그렇다면 액터 모델은 무엇이 좋을까요? EJB 컨테이너 관리 트랜잭션에 대한 정확한 설명 : 분산 트랜잭션 또는 임의의 종류의 분산 알고리즘을 사용하여 자체 클러스터링 알고리즘을 구현하려면 액터 모델을 기본 메커니즘으로 고려해야합니다. 모델 검사, 시간 논리 또는 동시 또는 분산 알고리즘의 정확성 증명에 익숙하다면 액터 모델의 정의가 정확함을 입증하는 데 매우 적합한 수학적 추상임을 알 수 있습니다.  (역주:  왜 그런지에 대한 약간의 힌트는 줄테니 니가 알아서 찾아봐라 네요. ㅜㅜ ) 

액터가 메시지를 받으면 1) 다른 (일관성있는) 상태로 전환하고, 2) 다른 액터를 만들고, 3) 다른 액터에 메시지를 보냅니다. 우리는 이것을 액터 전환이라고 부를 것입니다. 액터 모델 구현은 이러한 작업이 원자 적으로 또는 최소한 설명한 세 가지 단계로 수행되어야합니다. 또한 액터가 한 번에 하나의 메시지를 받고 이들 모든 단계를 수행 할 때까지 다음 메시지를 받지 못하는 것이 중요합니다. 액터는 또한 결정적인 방식으로 행동해야합니다. 즉, 상태와 메시지가 주어지면 항상 동일한 액터 전환을 만들어야 함을 의미합니다. 액터는 메시지에 대한 응답으로 만 전환을 만듭니다. 일반 프로세스와 달리 액터는 자발적으로 상태를 변경하지 않으며 액터 외부의 어떤 것도 스스로 상태를 변경하지 않습니다.

이제 전체 분산 시스템을 액터 모음으로 설명 할 수 있습니다. 각각은 고유 한 상태를 가지며 순환 메시지들의 모음으로 구성됩니다.

시스템 전환은 다음 중 하나에서 이루어집니다.

* 액터 전환
* 액터 충돌
* 메시지를 잃어버리다.
* 외부 메시지가 시스템 (이벤트)에 도입

시스템 상태가 주어지면, 우리는 거시서 부터 가능한 시스템 전환이 무엇인지를 알게 될 것입니다. 이를 통해 우리는 도달 가능한 상태와 도달 할 수없는 상태에 대해 수학적으로 추론 할 수 있습니다. 우리가 구현하고자하는 특정 알고리즘이 주어지면, 우리는 일반적으로 부정확 한 상태를 구성하는 것을 정의하고 그러한 상태에 도달 할 수 없다는 것을 이상적으로 증명할 것입니다. 또는 잘못된 상태가 발생하여 알고리즘에 결함이 있음을 증명할 수 있습니다.

일반적으로 동시 및 분산 소프트웨어 테스트는 어렵고 신뢰할 수 없습니다. 수학적 증명과 매우 유사한 프로그래밍 모델을 사용하면 훨씬 쉽게 테스트 할 수 있습니다. 먼저 각 액터 전환이 단일 스레드이며 결정적이며 종료되기 때문에 액터를 독립적으로 테스트하고 액터가 액터 전환을 올바르게 구현하는지 여부를 확인하는 것이 훨씬 쉽습니다. 둘째, 프로세스 충돌 및 메시지 손실을 포함하여 전체 시스템의 특정 시나리오를 시뮬레이션 할 수 있습니다. 이는 동시성 논리가 올바르다는 것을 보장하지는 않지만 일부 오류 시나리오를 감지 할 수 있으며 시스템 변경으로 인해 이러한 특성이 손상되지 않도록 테스트를 작성할 수 있습니다.  우리는 또한 속성 기반 테스트를 사용할 수 있으며 모델 구현을 직접 점검 할 수 있습니다.

현실 세계에서 이런 식으로 일하는 데 하나의 큰 장애물이 있습니다. 거의 모든 주요 액터 프레임 워크에 의해 구현 된 receive () 문입니다. 이것은 액터 전환의 원자성을 완전히 깨고, 차단할 수 있는 능력을 부여하며, 액터 테스트를 어렵게 만들고, 전체 시스템을 정확성 교정에 사용할 수있는 수학적 모델로 매핑하기가 어렵습니다. Receive는 호출되지 않은 (not invoked) 액터에 의해 구현 된 메소드 여야합니다.

사실 많은 알고리즘의 경우 스레드를 사용하고 요청을 차단하는 코드는 액터 기반 구현보다 더 읽기 쉽습니다. 액터는 논리가 다른 장소로 퍼져 있기 때문에 본질적으로 코드 리딩이 힘듭니다. receive () 문을 추가하면  원래 논문에 설명 된 액터 모델이 우리에게 준 멋진 기능을 모두 사용할 수 없게됩니다. 현재 액터 프레임 워크는 프로그래밍 모델의 단점인 스레드와 액터의 절충안입니다.

결론적으로, 제대로 구현되고 사용된다면 액터 모델에는 문제가 없으나 쉽지는 않습니다.


Comments