[Akka.NET] Akka.NET Helper 정의

참조


소개

  • Akka.NET은 Helper 클래스 및 몇가지 패턴들을 제공해 주면서, 프로그래밍 함에 있어서 좀 더 편리한 방법을 제공해 주고 있습니다.
  • 일반적으로, Actor에서 다른 Actor에게 메시지를 보내려면 ActorSelection 을 이용해 ActorPath를 길게 입력을 해주어야 합니다.
  • 하지만 이렇게 길게 경로를 직접 입력해야 하는 경우, 오타와 사용자 에러가 쉽게 발생할 수 있는 문제가 있습니다.
  • 때문에 Akka.NET에서는 몇가지 Helper 클래스를 제공하여 Path를 좀더 관리하기 수월하고 사용도 쉽게 할 수 있도록 제공합니다.

예제 코드

  • 실제로 어떻게 Helper 클래스들을 작성하고 사용하는지 예제 코드를 통해서 보여 드리도록 하겠습니다.

Helper 클래스 사용 전

using Akka.Actor;
using System;
using System.Threading;

namespace interfaceTest
{
    class Program
    {
        static void Main(string[] args)
        {
            //액터 시스템 생성
            ActorSystem actorSystem = ActorSystem.Create("actorSystem");

            Console.WriteLine($"{Thread.CurrentThread.ManagedThreadId} Main : 프로그램 시작");

            //RootActor1 액터 생성
            IActorRef rootActor1 = actorSystem.ActorOf(
                ExampleRootActor1.Props(),
                "ExampleRootActor1"
                );

            // RootActor1 메시지 전달하기
            rootActor1.Tell(2021); // int 형 메시지
            rootActor1.Tell("메시지 보낸다.");
            rootActor1.Tell("메시지 받은 대로 출력해라.");

            //액터 시스템 종료 대기
            actorSystem.WhenTerminated.Wait();
        }
    }

    public class ExampleRootActor1 : ReceiveActor
    {
        public static Props Props()
        {
            return Akka.Actor.Props.Create(() => new ExampleRootActor1());
        }

        public ExampleRootActor1()
        {
            Receive<int>(value => Handle(value));
            ReceiveAny(value => Handle(value));
        }

        private void Handle(int value)
        {
            Console.WriteLine($"{Thread.CurrentThread.ManagedThreadId} {"ExampleRootActor1"} <int> : {value}");
        }

        private void Handle(object value)
        {
            Console.WriteLine($"{Thread.CurrentThread.ManagedThreadId} {"ExampleRootActor1"} <object> : {value}");
        }
    }
}

Helper 클래스 사용 후

  • 아래 예제 코드에서 Helper 클래스는 ActorMetaData, ActorPaths 2개 입니다.
using Akka.Actor;
using System;
using System.Threading;

namespace interfaceTest
{
    class Program
    {
        static void Main(string[] args)
        {
            //액터 시스템 생성
            ActorSystem actorSystem = ActorSystem.Create("actorSystem");

            Console.WriteLine($"{Thread.CurrentThread.ManagedThreadId} Main : 프로그램 시작");

            //RootActor1 액터 생성
            IActorRef rootActor1 = actorSystem.ActorOf(
                ExampleRootActor1.Props(),
                ActorPaths.RootActor1.Name
                );

            // RootActor1 메시지 전달하기
            rootActor1.Tell(2021); // int 형 메시지
            rootActor1.Tell("메시지 보낸다.");
            rootActor1.Tell("메시지 받은 대로 출력해라.");

            //액터 시스템 종료 대기
            actorSystem.WhenTerminated.Wait();
        }
    }

    public class ExampleRootActor1 : ReceiveActor
    {
        public static Props Props()
        {
            return Akka.Actor.Props.Create(() => new ExampleRootActor1());
        }

        public ExampleRootActor1()
        {
            Receive<int>(value => Handle(value));
            ReceiveAny(value => Handle(value));
        }

        private void Handle(int value)
        {
            Console.WriteLine($"{Thread.CurrentThread.ManagedThreadId} {ActorPaths.RootActor1.Name} <int> : {value}");
        }

        private void Handle(object value)
        {
            Console.WriteLine($"{Thread.CurrentThread.ManagedThreadId} {ActorPaths.RootActor1.Name} <object> : {value}");
        }
    }

    public class ActorMetaData
    {
        public ActorMetaData(string name, ActorMetaData parent = null)
        {
            Name = name;
            Parent = parent;
            var parentPath = parent != null ? parent.Path : "/user";
            Path = $"{parentPath}/{Name}";
        }

        public string Name { get; private set; }
        public ActorMetaData Parent { get; set; }
        public string Path { get; private set; }
    }

    public static class ActorPaths
    {
        public static readonly ActorMetaData RootActor1 = new ActorMetaData("ExampleRootActor1");
        public static readonly ActorMetaData ChildActor1 = new ActorMetaData("childActor");
    }
}

정리

  • 액터에서 ActorPath는 매우 중요한 개념입니다.
  • 메시지를 다른 액터에게 보내려면 해당 액터의 Path를 명확히 알아야 합니다.
  • 하지만, 앞선 예제에서 액터 이름 및 Path를 직접 입력하게 되면 추후에 텍스트 입력으로 인한 에러 발생 가능성이 높아집니다.
  • 또한, 프로젝트가 커질수록 관리도 되지 않게 됩니다.
  • 때문에, ActorMetaData, ActorPaths 2개의 Helper 클래스를 생성하여 해당 클래스로 액터 Path를 생성하는 것이 바람직합니다.
728x90

이 글을 공유하기

댓글

Designed by JB FACTORY