Versions Compared

Key

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

Akka는 오픈 소스 툴킷으로, JVM 상의 동시성과 분산 애플리케이션을 단순화하는 런타임이다.
Akka는 동시성을 위한 여러 프로그래밍 모델을 지원하지만, Erlang으로부터 영향을 받아 actor 기반의 동시성이 두드러진다.
자바와 스칼라 언어 모두로 작성이 가능하다.

Akka가 .net 버전으로 포팅된것이 Akka.net이며
.net core 3.x 에서 작동 검증된 것만 정리하고 있습니다.

...

.NET Core 3.1 API 에 Akka.net 탑재해보겠습니다.

시작 템플릿

Image Added

시작 템플릿은 .Net Core 3.1 API 를 사용하였으며, Docker 지원 옵션을 추천합니다. ( 도커 개발환경 지원)

샘플에서 프로젝트명은  AkkaNetCore 로 생성 하였습니다.

라이브러리 추가

Code Block
themeEmacs
<PackageReference Include="Akka" Version="1.3.17" />
<PackageReference Include="Akka.Cluster" Version="1.3.17" />
<PackageReference Include="Akka.Cluster.Tools" Version="1.3.17" />
<PackageReference Include="Akka.DI.Extensions.DependencyInjection" Version="1.3.2" />    
<PackageReference Include="Akka.Logger.NLog" Version="1.3.5" />
<PackageReference Include="NLog.Web.AspNetCore" Version="4.8.1" />
  • Akka : 베이스 이며 로컬 액터만 사용한다고 하면 이것만으로 충분하다.
  • Akka.Cluster : 클러스터는 리모트기능을 포함하고 있으며 , 작성된 액터를 원격으로 조직화할때 사용된다.
  • Akka.Cluster.Tools : 클러스터를 쉽게 구성할수 있는 툴들이 추가되어있다. ( ex>싱글톤 클러스터 )
  • Akka.DI.Extensions.DependencyInjection : 액터에 의존성 주입을 할수 있게한다.(옵션)
  • Akka.Logger.NLog : 액터 메시지 로그 어댑터가 Nlog를 활용할수 있게한다.
  • Nlog.Web.AspNetCore : Net Core에서 Nlog(로깅 툴)를 활용할수 있게한다.

누겟이나 프로젝트 편집을 통해 의존 라이브러리 추가가 가능합니다.

Akka Extensions

Akka System및 구성요소(액터,설정) 등을 편리하게 사용하기 위해 사용자 정의 셋팅 파일을 추가합니다.

이 파일은 닷넷 능력치에따라, 필자가 작성한 방법보다 더 편리한 클래스로 개선가능합니다. 

Code Block
themeEmacs
titleAkkaBoostrap - 액터시스템을 싱글톤으로 등록
collapsetrue
using System;
using Akka.Actor;
using Akka.Cluster.Tools.Singleton;
using Microsoft.Extensions.DependencyInjection;

namespace AkkaNetCore.Extensions
{
    public static class AkkaBoostrap
    {
        public static IServiceCollection AddAkka(this IServiceCollection services, ActorSystem actorSystem)
        {
            // Register ActorSystem
            services.AddSingleton<ActorSystem>((provider) => actorSystem );
            return services;
        }
        
        public static IActorRef BootstrapSingleton<T>(this ActorSystem system, string name, string role = null) where T : ActorBase
        {
            var props = ClusterSingletonManager.Props(
                singletonProps: Props.Create<T>(),
                settings: new ClusterSingletonManagerSettings(name, role, TimeSpan.FromSeconds(10), TimeSpan.FromSeconds(3)));

            return system.ActorOf(props, typeof(T).Name);
        }

        public static IActorRef BootstrapSingletonProxy(this ActorSystem system, string name, string role, string path, string proxyname)
        {
            var props = ClusterSingletonProxy.Props(
                singletonManagerPath: path,
                settings: new ClusterSingletonProxySettings(name, role, TimeSpan.FromSeconds(1), 100));

            return system.ActorOf(props, proxyname);
        }
    }
}
Code Block
themeEmacs
titleAkkaLoad - 설정로드및 액터 참조 객체관리
using System;
using System.Collections.Concurrent;
using System.IO;
using System.Text;
using Akka.Actor;
using Akka.Configuration;
using Microsoft.Extensions.Configuration;
using AkkaConfig = Akka.Configuration.Config;

namespace AkkaNetCore.Config
{
    public class AkkaLoad
    {
        public static ConcurrentDictionary<string, IActorRef> ActorList = new ConcurrentDictionary<string, IActorRef>();

        public static void RegisterActor(string name, IActorRef actorRef)
        {
            if (ActorList.ContainsKey(name)) throw new Exception("이미 등록된 액터입니다.");
            ActorList[name] = actorRef;
        }

        public static IActorRef ActorSelect(string name)
        {
            return ActorList[name];
        }

        public static AkkaConfig Load(string environment, IConfiguration configuration)
        {
            if(environment.ToLower()!= "production")
            {
                environment = "Development";
            }

            return LoadConfig(environment, "akka{0}.conf", configuration);
        }

        private static AkkaConfig LoadConfig(string environment, string configFile, IConfiguration configuration)
        {
            string akkaip = configuration.GetSection("akkaip").Value ?? "127.0.0.1";
            string akkaport = configuration.GetSection("akkaport").Value ?? "5100";
            string akkaseed = configuration.GetSection("akkaseed").Value ?? "127.0.0.1:5100";
            string roles = configuration.GetSection("roles").Value ?? "akkanet";

            var configFilePath = string.Format(configFile, environment.ToLower() != "production" ? string.Concat(".", environment) : "");
            if (File.Exists(configFilePath))
            {
                string config = File.ReadAllText(configFilePath, Encoding.UTF8)
                    .Replace("$akkaport", akkaport)
                                .Replace("$akkaip", akkaip)
                                .Replace("$akkaseed", akkaseed)
                                .Replace("$roles", roles);

                var akkaConfig = ConfigurationFactory.ParseString(config);

                Console.WriteLine($"=== AkkaConfig:{configFilePath}\r\n{akkaConfig}\r\n===");
                return akkaConfig;
            }
            return Akka.Configuration.Config.Empty;
        }
    }
}




어플리케이션 로깅

위 순서대로 코드 셋팅이 성공하면 구동후 위와같은 로깅을 볼수 있습니다.

...