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

Compare with Current View Page History

« Previous Version 4 Next »

결함을 허용하지 않는 시스템은, 역설적으로 결함에 대응을 하지 않겠다란 의미입니다.

ActorSystem 은 결함을 허용함으로(결함을 발생시키겠다란 의미 아님)

장애발생시 감시할수있는 장치를 제공하고 , 사용자가 직접 대처할수 있는 다양한 전략을

선택하거나 응용프로그램에 설계할수가 있습니다.


장애 대응 설계


 액터 장애처리모델은 자기자신이 아닌 자신의 부모를 통해 정의가 가능하며

어떠한 액터의 장애를 다음과 같이 설계하고 룰을 정의한다고 합시다.

OOP 예외처리 모델에서 자식이 부모를 책임질수있는 구조적 정의는 불가능합니다.


다음과 같이, 장애대응 플랜을 세웠다고 가정해봅시다.

  • 장애 발생시 1분이내에 10번만 시도할수 있다. (복구 플랜)
  • 액터 작동시 널참조로인한 예외는 재시작하여 복구한다.
  • 액터 작동시 인자값  익셉션 에러일시, 해당 액터를 Stop시킨다.


Test Plan

  • 테스트에 사용할 액터를 생성한다.  부모 : supervisor , 자식 : child1
  • child1액터에게 널 예외 유발시킨다.
  • child1액터 crash 및 복구확인
  • child1에게 메시지보내어 작동중인지 확인
  • child1액터에게 인자값 예외 유발시킨다.
  • child1가 crash가 된것 확인
  • child1에게 메시지를 보내 사살확인 


구현및 실행코드



Actor 설계
    public class Supervisor : UntypedActor
    {
        private readonly ILoggingAdapter log = Context.GetLogger();        

		//장애처리 룰을 정의합니다.
        protected override SupervisorStrategy SupervisorStrategy()
        {
            return new OneForOneStrategy(
                maxNrOfRetries: 10,	//최고 시도횟수
                withinTimeRange: TimeSpan.FromMinutes(1),	//최고 시도 시간
                localOnlyDecider: ex =>
                {
                    // Exception별  복구전략
                    if( ex is ArithmeticException )
                        return Directive.Resume;
                    else if( ex is NullReferenceException)
                        return Directive.Restart;
                    else if (ex is ArgumentException)
                        return Directive.Stop;
                    else
                        return Directive.Escalate;                    
                });
        }
       

        protected override void OnReceive(object message)
        {
            if (message is string)
            {
                string msg = message as string;

                if ( msg.Contains("create-") )
                {
                    string childName = msg.Split('-')[1];
                    log.Info("CreateChildActor:" + childName);
                    var childActor = Context.ActorOf<Child>(childName);
                    Context.Watch(childActor);
                    Sender.Tell(childActor);
                }                                                
            }
        }
    }

    public class Child : UntypedActor
    {
        private int state = 0;
        private readonly ILoggingAdapter log = Context.GetLogger();

        protected override void OnReceive(object message)
        {            
            if( message is Exception)
            {
                throw message as Exception;
            }
            else if (message is int)
            {
                state = (int)message;
            }
            else if (message is string)
            {
                switch (message as string)
                {
                    case "get":
                        log.Info("Active Check");  //메시지를 받을수 있는지 체크
                        Sender.Tell(state);
                        break;
                }
            }
        }

        protected override void PreRestart(Exception reason, object message)
        {
            log.Info("Actor Restart - reason:" + reason.GetType().Name );   //액터 재 시작된이 야기된 이유를 , 재시작시 알수 있습니다.
        }
    }
실행코드
            using (ActorSystem actorSystem = ActorSystem.Create("ServiceA"))
            {
                IActorRef supervisor = actorSystem.ActorOf<Supervisor>("supervisor");
                IActorRef child = supervisor.Ask("create-child1").Result as IActorRef;

                child.Tell(new NullReferenceException() );   //강제로 예외발생...                
                Task.Delay(1000).Wait();    //복구를 기다려준다.
                child.Tell("get");

                child.Tell(new ArgumentException() );   //강제로 예외발생...
                Task.Delay(1000).Wait();    //복구를 기다려준다.
                child.Tell("get");

                Task.Delay(3000).Wait();    //종료 지연시간

            }

[INFO][2017-09-13 오전 7:34:22][Thread 0029][[akka://ServiceA/user/supervisor#740151541]] CreateChildActor:child1
[INFO][2017-09-13 오전 7:34:22][Thread 0029][[akka://ServiceA/user/supervisor#740151541]] SomeException:
[ERROR][2017-09-13 오전 7:34:22][Thread 0029][akka://ServiceA/user/supervisor/child1] 개체 참조가 개체의 인스턴스로 설정되지 않았습니다.
Cause: System.NullReferenceException: 개체 참조가 개체의 인스턴스로 설정되지 않았습니다.
위치: ServiceA.STUDY.Child.OnReceive(Object message) 파일 D:\work\hobby\git.webnori.com\akkastudy\Solution\ServiceA\STUDY\SupervisorTestData.cs:줄 64
위치: Akka.Actor.UntypedActor.Receive(Object message)
위치: Akka.Actor.ActorBase.AroundReceive(Receive receive, Object message)
위치: Akka.Actor.ActorCell.ReceiveMessage(Object message)
위치: Akka.Actor.ActorCell.Invoke(Envelope envelope)
[INFO][2017-09-13 오전 7:34:22][Thread 0029][[akka://ServiceA/user/supervisor/child1#716613491]] Actor Restart - reason:NullReferenceException
[INFO][2017-09-13 오전 7:34:23][Thread 0005][[akka://ServiceA/user/supervisor/child1#716613491]] Active Check
[INFO][2017-09-13 오전 7:34:23][Thread 0021][[akka://ServiceA/user/supervisor#740151541]] SomeException:
[ERROR][2017-09-13 오전 7:34:23][Thread 0021][akka://ServiceA/user/supervisor/child1] 값이 예상 범위를 벗어났습니다.
Cause: System.ArgumentException: 값이 예상 범위를 벗어났습니다.
위치: ServiceA.STUDY.Child.OnReceive(Object message) 파일 D:\work\hobby\git.webnori.com\akkastudy\Solution\ServiceA\STUDY\SupervisorTestData.cs:줄 64
위치: Akka.Actor.UntypedActor.Receive(Object message)
위치: Akka.Actor.ActorBase.AroundReceive(Receive receive, Object message)
위치: Akka.Actor.ActorCell.ReceiveMessage(Object message)
위치: Akka.Actor.ActorCell.Invoke(Envelope envelope)
[INFO][2017-09-13 오전 7:34:23][Thread 0029][akka://ServiceA/deadLetters] Message Int32 from akka://ServiceA/user/supervisor/child1 to akka://ServiceA/deadLetters was not delivered. 1 dead letters encountered.
[INFO][2017-09-13 오전 7:34:24][Thread 0043][akka://ServiceA/user/supervisor/child1] Message String from akka://ServiceA/deadLetters to akka://ServiceA/user/supervisor/child1 was not delivered. 2 dead letters encountered.
[DEBUG][2017-09-13 오전 7:34:27][Thread 0044][ActorSystem(ServiceA)] Disposing system
[DEBUG][2017-09-13 오전 7:34:27][Thread 0044][ActorSystem(ServiceA)] System shutdown initiated






  • No labels