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

Compare with Current View Page History

« Previous Version 16 Next »

이번장에서는 Actor의 기능을 확장하여 유용한 몇가지 기능들을 살펴보겠습니다.

Untyped Actor

Untyped Actor
    public class MyActorSame : UntypedActor
    {        
        protected override void OnReceive(object message)
        {
            if(message is string)
            {
                if (message as string == "createChild")
                {
                    Context.ActorOf<MyActor>("myChild");
                    Sender.Tell("Create Child Succed:myChild");
                }
                else
                {
                    Sender.Tell("RE:" + message);
                }
            }
            else if(message is SomeMessage)
            {
                Sender.Tell("RE:" + (message as SomeMessage).message );
            }
        }
    }

  Untyped Actor는, 이전 섹션에서 익힌 ReceiveActor 처럼 생성자에서 Type별로 메시지 처리기를 등록하는게 아닌 , OnReceive에서 직관적으로 수신처리가 가능합니다.  ReceiveActor 가 수신가능 액트로 기능이 명료하고 좀더 추상화가 되었다면

Untyped Actor 는 좀더 커스텀한 액트 설계시 상속을 받아 재정의 합니다.


ACTOR의 확장기능을 설명하기위해 이제부터는 UntypedActor를 사용하면서 진행하겠습니다.

Become/Unbecome


  사용목적 : 메시지 처리기가 어떠한 메시지에 따라 패턴이 변한다고 가정합시다.

이러한 경우,어떠한 패턴이없다면 상태값을 내부변수로 두고 이값에따라 다중 IF문을 통해

분기처리를 할것입니다. 메시지 처리에대한 중첩 IF문이 발생하기때문에 가독성이 떨어지거나

유지보수가 힘들수 있습니다. 이경우 메시지 처리기를 좀더 유연하게 설계가가능합니다.

FSM(Finite-state machine) 을 지원하기위한 기능입니다.


  • Become : 메시지 처리기를 변경합니다.
  • Unbecome : 기본 메시지 처리로 변경합니다.

처리기가 변하는 Actor
	//foo 라고하면 행복해졌다가, bar라고하면 화나는 ACTOR , 동일한 상태에서는 상태변경없이 메시지전송
    public class HotSwapActor : UntypedActor
    {
		//기본탑재 로그,이제부터는 시간,스레드,액터정보등이 표시된 console.writeline대신 AKKA LOG를 사용하겠습니다.  using Akka.Event
        private ILoggingAdapter log = Context.GetLogger();          
        protected override void OnReceive(object message)
        {
            log.Info("NORMAL:"+message.ToString());
            switch (message as string)
            {
                case "foo":                    
                    log.Info("행복해짐");
                    Become(Happy);
                    break;
                case "bar":
                    log.Info("화남");
                    Become(Angry);
                    break;
            }
        }

        private void Angry(object message)
        {
            log.Info("Angry:" + message.ToString());
            switch (message as string)
            {
                case "foo":
                    log.Info("행복해짐");
                    Become(Happy);
                    break;
                case "bar":                    
                    log.Info("이미 화가났다.");
                    Sender.Tell("이미 화가났다.");
                    break;
            }
        }

        private void Happy(object message)
        {
            log.Info("Happy:" + message.ToString());
            switch (message as string)
            {
                case "foo":
                    log.Info("이미 행복하다.");
                    Sender.Tell("이미 행복하다.");
                    break;
                case "bar":
                    log.Info("화남");
                    Become(Angry);
                    break;
            }
        }
    }

TestCode:foo 라고하면 행복해졌다가, bar라고하면 화나는 ACTOR 결국 행복해짐
        protected void SomeTest3() //BecomeTest
        {
            IActorRef myActor = actorSystem.ActorOf<HotSwapActor>("myactor");            
            myActor.Tell("bar");
            myActor.Tell("foo");
            myActor.Tell("bar");
            myActor.Tell("foo");
            myActor.Tell("bar");
            myActor.Tell("bar");
            myActor.Tell("foo");
        }

[INFO][2017-09-05 오전 6:50:10][Thread 0005][[akka://ServiceA/user/myactor#16204
11193]] NORMAL:bar
[INFO][2017-09-05 오전 6:50:10][Thread 0005][[akka://ServiceA/user/myactor#16204
11193]] 화남
[INFO][2017-09-05 오전 6:50:10][Thread 0005][[akka://ServiceA/user/myactor#16204
11193]] Angry:foo
[INFO][2017-09-05 오전 6:50:10][Thread 0005][[akka://ServiceA/user/myactor#16204
11193]] 행복해짐
[INFO][2017-09-05 오전 6:50:10][Thread 0005][[akka://ServiceA/user/myactor#16204
11193]] Happy:bar
[INFO][2017-09-05 오전 6:50:10][Thread 0005][[akka://ServiceA/user/myactor#16204
11193]] 화남
[INFO][2017-09-05 오전 6:50:10][Thread 0005][[akka://ServiceA/user/myactor#16204
11193]] Angry:foo
[INFO][2017-09-05 오전 6:50:10][Thread 0005][[akka://ServiceA/user/myactor#16204
11193]] 행복해짐
[INFO][2017-09-05 오전 6:50:10][Thread 0005][[akka://ServiceA/user/myactor#16204
11193]] Happy:bar
[INFO][2017-09-05 오전 6:50:10][Thread 0005][[akka://ServiceA/user/myactor#16204
11193]] 화남
[INFO][2017-09-05 오전 6:50:10][Thread 0005][[akka://ServiceA/user/myactor#16204
11193]] Angry:bar
[INFO][2017-09-05 오전 6:50:10][Thread 0005][[akka://ServiceA/user/myactor#16204
11193]] 이미 화가났다.
[INFO][2017-09-05 오전 6:50:10][Thread 0005][[akka://ServiceA/user/myactor#16204
11193]] Angry:foo
[INFO][2017-09-05 오전 6:50:10][Thread 0005][[akka://ServiceA/user/myactor#16204
11193]] 행복해짐
[INFO][2017-09-05 오전 6:50:10][Thread 0006][akka://ServiceA/deadLetters] Messag


액트의 Lifecyle모니터링





액트접근 주소체계



잠시 실습없이, Actor를 접근하는 주소체계에대해 설명 드리겠습니다.  ActorPath는 총 4가지로 구분이 되며 

http의 RestAPI의 주소체계와 거의 흡사하다고 볼수 있습니다.

여기서 Protocol,ActorSystem,Address 요소를 생략하면 ex>'user/actorName1'  자신의 LocalSystem에만 접근하겠다란 의미입니다.


4요소

  • Protocol : AKKA를 사용하는 프로토콜임을 알림
  • ActorSystem : 주로 어플리케이션 하나의 이름으로, ActorSystem 최초 생성시 이름지정
  • Address : 네트워크 주소로 ip:port 로 표현
  • Path : 서비스 개발자가, 계층적으로 배치한 Actor 이름


RestAPI호출 접근법과는 큰차이가 없어보이나 내부적으로는 피어투피어 실시간 통신으로 메시지가 처리가됩니다.

다음 RemoteActor실습시 가상의 서비스 시나리오를 만들어 성능 차이를 프로파일링 비교해보겠습니다. 

  • RESTAPI 호출 VS RemoteActor 호출
  • 항상 DB Read 가 발생하는 RESTAPI VS Actor를 사용하여 DB Read가 발생하지않는 RESTAPI
  • Unable to render Jira issues macro, execution error.







  • No labels