Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Info

ReceiveActor은 Actor의 기본 메시지 처리기가 정의된 기본 클래스이며

대부분의 기본 메시지처리는 ReceiveActor에서 가능합니다.


액터모델의 특징 요약

  • 동시및 분산 시스템작성을 위해 높은수준의 추상화제공
  • 개발자가 명시적 잠금처리및 스레드 관리 안해도됨
  • 이로인해 병렬 시스템 작성에 용이


ActorSystem 주요 메서드

  • Create : ActorSystem을 생성( 어플케이션당 하나 )
  • ActorOf : 자신의 레벨(탑)하위에 액터를 추가
  • ActorSelection : 접근경로 기반으로 액터를 선택함


Actor 메시지 전송 주요 메서드

  • Tell : 알리기만 하여, 결과값 신경안씀
  • Ask : 질의를 하며 요청에대한 결과값을 지켜봄(비동기), Result 조합시 기다림(동기처리)
  • Sender : Actor내에서 자신에게 메시지를 보낸, 발신자 ( 응답용도 )



Actor 정의(+메시지설계)

...


Code Block
languagec#
themeEmacs
titleReceiveActor
linenumberstrue
 
    public class SomeMessage
    {
        public string message { set; get; }
    }

    public class MyActor : ReceiveActor
    {        

        public MyActor()
        {
            Receive<string>(message => {
                Sender.Tell("RE:" + message);                
            });

            Receive<SomeMessage>(message => {
                Sender.Tell("RE:" + message.message);
            });
        }
    }


Actor의 는 Actor는, 메시지를 유연하게 보낼수 있는 가장작은 기본객체이며 송수신 정의하는 가장작은 객체의 정의 이며, 능동적 객체라고 볼수 있다.


Actor설계시 기본적으로 다음을 고려한다우리는 Actor설계시다음을 생각하면 된다. 이것은 마치 특정API 설계시 하는 고민과 똑같다.

...

위 정의 코드는 그러한 설계에대해 구현을 한것이며, 다음과 같은 스펙을 가진다.

  • message 문자열 오브젝트를 가진, SomeMessage 존재
  • 메시지를 받게 될시 , 접두어 "RE:" 를 붙여 해당 메시지를 그대로 돌려줌
  • 응답해야할 Type이 정해지지 않고 다양한 요청에 대해 다양한 Type으로 응답가능

 위 코드에서 ReceiveActor 생성자에서 , Type  위코드에서 생성자에서 , 패턴 매칭하여 메시지 처리기가 가능한것은 , ReveiveActor의 Receive의 추상화덕분이며

IF문이나 스위치문없이 생성자에서 , 처리할 패턴별로 처리기가 등록이 가능한것은 C#의 문법지원때문인데

개발 C# 언어학적으로 파악하고자 하면 ( 템플릿 람다 /함수형/ 델리게이트 특성) 참조하여 작동원 파악 심화 학습이 가능합니다.


어쨋든, 우리는 아주 우리의  아주 짧은 코드로 액터 메시지 처리기 설계가 끝이 났습니다.

액터 생성

...


Code Block
languagec#
themeEmacs
linenumberstrue
        protected void SomeTest1()
        {
            IActorRef myActor = actorSystem.ActorOf<MyActor>("myactor");
            Console.WriteLine(myActor.Ask("Hello Akka").Result);
        }
Expand
titleResult

RE:Hello AKKA


처음에 설계한 MyActor를 myActor란 이름으로 생성하고

Heelo Akka란 메시지를 전송하여 그 결과값을 출력하는 예제입니다.

보낼수 있는 명령 Type

  • Ask : 결과값을 기대할때 사용합니다. 비동기로 수신하며, 동기처리시 .Result를 붙입니다. ( C#의 Async 프로그래밍 )
  • Tell :  결과값이 필요 없을때 , 단지 전송만 하고 대기처리가 없습니다. 로직상 Tell에의해 어떠한 뒤늦은 결과값을 예상할수도 있습니다.


Child 액터 생성과 액터선택

...


자식 노드 생성

Code Block
languagec#
themeEmacs
linenumberstrue
            Receive<string>(message => {
                if (message == "createChild")
                {
                    Context.ActorOf<MyActor>("myChild");
                    Sender.Tell("Create Child Succed:myChild");
                }
                else
                {
                    Sender.Tell("RE:" + message);
                }
            });

문자열 수신부분을 수정을 하여,  createChild 란 문자열을 받을시 'myChild' 란 하위 노드의 액터를 생성하고

자식액터(하위노드) 의 생성을 반환하는 메시지를 응답하는 예제입니다.


이것을 작동시키는 코드는 아래와 같이 하면 되겠습니다.

특정노드를 선택하여, 자식 노드 동적으로만들고, 자식노드에게 메시지 보내기

Code Block
languagec#
themeEmacs
linenumberstrue
        protected void SomeTest2()
        {
            IActorRef myActor = actorSystem.ActorOf<MyActor>("myactor");
            Console.WriteLine(myActor.Ask("createChild").Result);
            Console.WriteLine(actorSystem.ActorSelection("/user/myactor").Ask("Hello Akka1").Result);
            Console.WriteLine( actorSystem.ActorSelection("/user/myactor/myChild").Ask("Hello Akka2").Result );
        }
Expand
titleResult

Create Child Succed:myChild
RE:Hello Akka1
RE:Hello Akka2


주로  어떠한 메시지를 받았을때, 동적으로 액터를 생성시 활용을 합니다.  REST API의 Endpoint체계는 다소 정적이지만

Actor의 EndPoint체계는 이러한 이유로 , 뎁스 추가 삭제가 자유롭습니다.


사용자가 만든 액터 루트의 최상위는 'user' 이며 만든 계층에따라 하위 뎁스로 가거나 수평으로 뻗어 가게 됩니다. 

actorSystem에 의해 어떠한 이름(myactor))으로 만들어졌다면  'user/myactor'
myactor가 어떠한 이름(myChild) 하위 노드를 만들었다면 'user/myactor/myChild' 이렇게 계층화가 됩니다.

그리고 , 액터시스템은 어떠한 액터라도 선택할수 있으며

actorSystem.ActorSelection( 액터주소).어떠한액션()  이러한 접근방식으로 메시지 전송이 가능합니다.


액터 생성 Factory화

...

Code Block
languagec#
themeEmacs
linenumberstrue
public class DemoActor : ReceiveActor
{
    private readonly int _magicNumber;

    public DemoActor(int magicNumber)
    {
        _magicNumber = magicNumber;
        Receive<int>(x =>
        {
            Sender.Tell(x + _magicNumber);
        });
    }

    public static Props Props(int magicNumber)
    {
        return Akka.Actor.Props.Create(() => new DemoActor(magicNumber));
    }
}

system.ActorOf(DemoActor.Props(42), "demo");

 자신의 액터 생성방식을 자신의 클래스내에서 정의하고 외부에 제공해주는것은 휼륭한 아이디어 입니다.



Info

Props

Actor생성을 위해 옵션을 지정하고, 이를 통해 액터 생성방법을 공유하기위한 구성클래스입니다.

몇가지 Props를 통한 다양한 액터 생성법


Props props1 = Props.Create(typeof(MyActor));
Props props2 = Props.Create(() => new MyActorWithArgs("arg"));
Props props3 = Props.Create<MyActor>();
Props props4 = Props.Create(typeof(MyActorWithArgs), "arg");