You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 32 Next »

Actor란?

액터는 매우 가벼운 동시성  엔터티들이다.  event-driven receive loop를 이용하여 비동기적 메시지를 처리한다.

메세지에 대응되는 패턴매칭은 액터의 행동을 나타내는 굉장히 편리한 방법이며

추상레벨을 높혀서 Akka 를 가져다가 사용하는 개발자들이  분산/병렬  코드를 작성하기 굉장히 쉽게 해준다.


  • 유사 패턴 : Active Object 패턴
  • 간단한 설명 : 비동기 메시지를 처리할수 있는 능동적 객체

간단한 용어설명


OOP와 비교해본 Actor Model


OOP

일반적 OOP에서 스레드 세이프한 객체 작성법
    public class DeepThought
    {
        private int state;

        public int State
        {
            get
            {
                lock (this)
                {
                    Thread.Sleep(3000); //나의 상태에대한 깊은 생각에 빠짐..나는누군가? 여긴어딘가?
                    return state;
                }                
            }

            set
            {
                lock (this)
                {
                    //깊은 생각에 빠질땐 누구도 건들지 말기를 바람,그대가 최고우선순위 스레드라할지라도
                    state = value;
                }                
            }
        }        
    }
var dt = new DeepThought()

Thread.new { console.log( dt.State ) }
Thread.new { dt.State=1 }

 자신의 상태변경및 제공을 멀티스레드에 안전한 방식으로 OOP를 설계한다고 가정하자

이 클래스는 이야기한다, '자신의 속성을 Lock(metex)를 걸어 , 누군가 나를  접근하고 있을때, 해당 오브젝트를 건들지마(또는 기달려야해)' 라고 이야기하고 있다.


일반적으로 OOP 관점에서는 스레드 세이프하다란 의미는 메스드사용시 공유객체를 Lock을 걸거나? 별도의 독립된 객체를 추가로 생성하여

동시처리,동시접근에대한 문제를 풀려고 한다. 공통점은 특정한 속성값이 멀티쓰레드에서 동시접근 제한 방지를 위해 공유가된다는 점이다.



접근공유문제와  동시성 문제 해결하기위해, 복잡한 쓰레드 모델을(CriticalSection,SpinLock,Mutex,Semaphore) 익혀야하며

클러스터 구성하기도 전에, 단일노드에서 효율적 동시성 접근문제에 대해 많은 고민을 해야합니다.

Actor

액터의 기본철학은, 액터가 차지하는 메모리 공간은 어느 다른 쓰레드혹은 동일한 액터에서도 자기자신의 속성을 접근할수 없다

를 원칙으로 한다. 다시말해 액터내부에 일어나는 일은 어느 누구와도 '공유'되지 않으며 죽음의 칵테일에서 

공유라는 속성을 제거함으로 멀티쓰레드와 관련된 문제의 대부분을 제거 하고 시작한다.

공유되지 않기때문에, 임계영역 처리를 위해  'lock' 'synchronized' 와 같은 부자연스러운 키워드가 필요없으며

쓰레드를 생성하고 관리할 필요가 없어진다.  즉, 비동기형 능동적 객체인 Actor를 어떻게  최적화해서

다중쓰레드로 관리할것인가의 문제는 ActorSystem이 해야할일이며, 개발코드와 분리된 옵션화를 통한 튜닝의 문제입니다.   ( http://doc.akka.io/docs/akka/2.5.3/scala/dispatchers.html )


Actor 설계 코드
public class MyActor: ReceiveActor
{
  //Actor모델 에서는 안전한 동시성처리를 위해 어떠한 프로퍼티(속성)도 공유가 필요없음으로, 속성 접근제한에 priave만으로 충분합니다.
  private readonly ILoggingAdapter log = Context.GetLogger();
  private int state =0;

  public MyActor()
  {
    Receive<string>(message => {
      log.Info("Received String message: {0}", message);
      Sender.Tell(state );
    });
    Receive<SomeMessage>(message => {...});
  }
}

//코드 변경 최소로 옵션만으로 로컬,원격,클러스터등러등의 작동 선택 전략이 가능하다.
var remoteActor = system.ActorSelection("akka.tcp://MyServer@127.0.0.1:8001/user/someActor"); 

// 질의를 하던지?(Ask), 단지 말만한다던지?(Tell), 결과를 기다리던지(Result)? 
// 객체 접근 기반이아닌 메시지 전송기반의 인터페이스를 사용하는 조금더 추상화된 모델이다.
var state = remoteActor.Ask("Hello").Result; 



Actor는 오로지 메시지만 주고 받으며 동시성을 달성하며,  결과값을 얻기위해서는 객체접근이아닌 질의를 해야한다.

이와같은 처리방식은 동일한 컨셉으로 로컬뿐아니라 리모트처리,분산처리등으로 확장이 될수가있다.


메시지 전송에의해서만, 처리가 되기때문에 확장및 동시성처리에 유연해집니다.


위 그림을 보면, 이러한 의문을 가질수 있습니다.  액터하나당? Thread를 하나사용하는것인가?

그러면 많은 액터를 많이 만들면 안되지 않는가? 

AKKA에서는 스레드풀 옵션에의해 이러한 문제를 튜닝으로 해결이 가능하며 개수 제한가능합니다.

실제 아무일을 하지 않는 액터는 스레드를 점유하지 않습니다. ( dispatcher가 액터들을 스레드풀에의해 효율적으로 관리함)

만약 어떠한 액터가 블락킹(처리시간이 많이걸리는)을 많이 발생하는 액터라고 가정하면..,

빠르게 작동되는 액터와 스레드사용 전략을 분리할 필요가 있습니다.


dispatcher-behaviour-on-good-code.png

프로세스 스레드 프로파일툴로, Actor의 실제 활동 측정을 통해 튜닝이 가능해집니다.

목적과 성능에따라 액터를 관리할 dispatcher를 분리하게되면 Actor의 성능에대한 문제 파악이 용이해집니다.

-번외 문서 : 서버 개발자의 성능 튜닝에대한 고뇌 )


my-blocking-dispatcher {
  type = Dispatcher
  executor = "thread-pool-executor"
  thread-pool-executor {
    fixed-pool-size = 16
  }
  throughput = 1
}
//이것은 런타임 코드가 아니라, 설정사항입니다. AKKA에서는 Thread를 직접 생성하는 코드를 작성하지 않습니다.

관련 액터들만, 스레드를 특정개수로 제한할수가 있으며  처리시간이 짧은 액터일경우 훨씬더 작은 수의 스레드로도 충분히 빠르게 작동을 합니다.

실제로 내부 장비에서 액터간 초당 50만 메시지가 처리가능하다라고 함 :  http://letitcrash.com/post/20397701710/50-million-messages-per-second-on-a-single


OOP설계방식으로 패킷을설계하고, TCP전송 프로토콜을 사용하여 멀티스레드 기법으로 고성능 전송을 구현한다고 했을시

1:1 안정적인 고성능 전송기능이될때까지 엄청난 노력을 기울여야할것입니다. (그것이 c++이던 java이던간에)

Akka-Actor모델은 이시간을  클러스터및 분산환경 메시지전송의 개발로직을 짤수있게 도와줍니다. 


이 부분에 대한 실습은 RemotActor,Route 실습에서 조금더 다루도록 하겠습니다.






















  • No labels