Exemple #1
0
        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IApplicationLifetime lifetime)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Error");
            }

            app.UseStaticFiles();

            app.UseRouting();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapBlazorHub();
                endpoints.MapFallbackToPage("/_Host");
            });

            lifetime.ApplicationStarted.Register(() =>
            {
                var actorName = "countActor";
                AkkaLoad.RegisterActor(actorName,
                                       actorSystem.ActorOf(Props.Create(() => new CountActor()),
                                                           actorName));
            });
        }
        public ClusterWorkActor()
        {
            id = Guid.NewGuid().ToString();
            //logger.Info($"Create ClusterMsgActor:{id}");
            msgCnt = 0;
            random = new Random();

            StatisticsActor = AkkaLoad.ActorSelect("SingleToneActor");

            ReceiveAsync <DelayMsg>(async msg =>
            {
                Context.IncrementMessagesReceived();

                if (msgCnt < 10)
                {
                    logger.Debug($"### Message ClusterMsgActor {msgCnt}");
                }
                msgCnt++;
                //랜덤 Delay를 줌( 외부 요소 : API OR DB )
                int auto_delay = msg.Delay == 0 ? random.Next(1, 100) : msg.Delay;
                await Task.Delay(auto_delay);

                Context.IncrementCounter("akka.custom.received1");
                msg.State = DelayMsgState.Completed;
                StatisticsActor.Tell(msg);

                if ((msgCnt % 100) == 0)
                {
                    logger.Info($"Msg:{msg} Count:{msgCnt} Delay:{auto_delay}");
                }
            });
        }
Exemple #3
0
        static public void Start(IApplicationBuilder app, ActorSystem actorSystem)
        {
            // http://wiki.webnori.com/display/AKKA/Actors

            // HelloActor 기본액터
            AkkaLoad.RegisterActor("helloActor" /*AkkaLoad가 인식하는 유니크명*/,
                                   actorSystem.ActorOf(Props.Create(() => new HelloActor("webnori")),
                                                       "helloActor" /*AKKA가 인식하는 Path명*/));

            var helloActor  = actorSystem.ActorSelection("user/helloActor");
            var helloActor2 = AkkaLoad.ActorSelect("helloActor");

            helloActor.Tell("hello");
            helloActor2.Tell("hello");

            // 밸브 Work : 초당 작업량을 조절
            int timeSec      = 1;
            int elemntPerSec = 5;
            var throttleWork = AkkaLoad.RegisterActor("throttleWork",
                                                      actorSystem.ActorOf(Props.Create(() => new ThrottleWork(elemntPerSec, timeSec)),
                                                                          "throttleWork"));

            // 실제 Work : 밸브에 방출되는 Task를 개별로 처리
            var worker = AkkaLoad.RegisterActor("worker", actorSystem.ActorOf(Props.Create <WorkActor>(),
                                                                              "worker"));

            // 밸브 작업자를 지정
            throttleWork.Tell(new SetTarget(worker));

            //StartLoadTestByRouter(app,actorSystem);
            //StartLoadTestByPingPong(app,actorSystem);

            //StartKafkaTest(app, actorSystem);
        }
 public ActorTestController()
 {
     basicActor       = AkkaLoad.ActorSelect("basic");
     printerActor     = AkkaLoad.ActorSelect("printer");
     highPassActor    = AkkaLoad.ActorSelect("highpass");
     cashPassActor    = AkkaLoad.ActorSelect("cashpass");
     clusterRoundbin1 = AkkaLoad.ActorSelect("clusterRoundRobin");
     singleToneActor  = AkkaLoad.ActorSelect("SingleToneActor");
     throttleActor    = AkkaLoad.ActorSelect("throttleActor");
 }
Exemple #5
0
        // This method gets called by the runtime. Use this method to add services to the container.
        // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
        public void ConfigureServices(IServiceCollection services)
        {
            var envName    = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
            var akkaConfig = AkkaLoad.Load(envName, Configuration);

            actorSystem = ActorSystem.Create("AkkaDotBootSystem", akkaConfig);
            services.AddAkka(actorSystem);

            services.AddRazorPages();
            services.AddServerSideBlazor();
            services.AddSingleton <WeatherForecastService>();
        }
Exemple #6
0
        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            //services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
            services.AddControllers();

            services.AddSingleton(Configuration.GetSection("AppSettings").Get <AppSettings>());// * AppSettings

            // 액터에 DI적용시 사용
            services.AddSingleton <KafkaService>();
            services.AddScoped <TonerActor>();
            services.AddScoped <PrinterActor>();

            // Swagger
            services.AddSwaggerGen(options =>
            {
                options.SwaggerDoc("v1", new OpenApiInfo
                {
                    Version        = "v1",
                    Title          = AppName,
                    Description    = $"{AppName} ASP.NET Core Web API",
                    TermsOfService = new Uri("http://wiki.webnori.com/display/codesniper/TermsOfService"),
                    Contact        = new OpenApiContact
                    {
                        Name  = Company,
                        Email = Email,
                        Url   = new Uri(CompanyUrl),
                    },
                    License = new OpenApiLicense
                    {
                        Name = $"Document",
                        Url  = new Uri(DocUrl),
                    }
                });

                // Set the comments path for the Swagger JSON and UI.
                var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
                var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
                options.IncludeXmlComments(xmlPath);
            });

            // *** Akka Service Setting
            var envName     = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
            var akkaConfig  = AkkaLoad.Load(envName, Configuration);
            var actorSystem = ActorSystem.Create(SystemNameForCluster, akkaConfig);
            var provider    = services.BuildServiceProvider();

            actorSystem.UseServiceProvider(provider);
            services.AddAkka(actorSystem);

            // API주소룰 소문자로...
            //services.AddRouting(options => options.LowercaseUrls = true);
        }
Exemple #7
0
        static public void StartLoadTestByRouter(IApplicationBuilder app, ActorSystem actorSystem)
        {
            //##################################################################
            //##### TPS 측정편 - 액터성능
            //##### 라우터
            //#####
            //##################################################################

            int testHitCount   = 400000;
            int distributedCnt = 50;

            //튜닝요소
            //custom-dispatcher , custom-task-dispatcher , default-fork-join-dispatcher
            string disPacther = "custom-task-dispatcher";

            var roundPool = AkkaLoad.RegisterActor("roundPool",
                                                   actorSystem.ActorOf(Props.Create(() => new InfiniteReflectionActor()).WithDispatcher(disPacther)
                                                                       .WithRouter(new RoundRobinPool(distributedCnt)),
                                                                       "roundPool"));

            // Wait for all tasks to complete.
            Task[] tasks = new Task[distributedCnt];
            for (int i = 0; i < distributedCnt; i++)
            {
                tasks[i] = Task.Run(() => {
                    for (int hitidx = 0; hitidx < testHitCount; hitidx++)
                    {
                        roundPool.Tell(new DistributedMessage()
                        {
                            Message = "test"
                        });
                    }
                });
            }
            try
            {
                //Task.WaitAll(tasks);
                Console.WriteLine("Completed,Tell");
            }
            catch (AggregateException ae)
            {
                Console.WriteLine("One or more exceptions occurred: ");
                foreach (var ex in ae.Flatten().InnerExceptions)
                {
                    Console.WriteLine("   {0}", ex.Message);
                }
            }
        }
Exemple #8
0
        static public void StartLoadTestByPingPong(IApplicationBuilder app, ActorSystem actorSystem)
        {
            //##################################################################
            //##### TPS 측정편 - 액터성능
            //##### 핑퐁
            //#####
            //##################################################################


            //튜닝요소
            //custom-dispatcher , custom-task-dispatcher , default-fork-join-dispatcher
            string disPacther       = "custom-task-dispatcher";
            int    pipongGroupCount = 1; // 핑퐁그룹,탁구대를 늘릴수있다. ( 2인1조)
            int    ballCount        = 6; // 핑퐁에 사용된 공개수

            // 무한전송 셋트...
            for (int i = 0; i < pipongGroupCount; i++)
            {
                string actorFirstName  = "infiniteReflectionActorA" + i;
                string actorSecondName = "infiniteReflectionActorB" + i;

                // 무한전송 Test Actor생성
                var infiniteReflectionActorA = AkkaLoad.RegisterActor(actorFirstName,
                                                                      actorSystem.ActorOf(Props.Create(() => new InfiniteReflectionActor()).WithDispatcher(disPacther),
                                                                                          actorFirstName));

                var infiniteReflectionActorB = AkkaLoad.RegisterActor(actorSecondName,
                                                                      actorSystem.ActorOf(Props.Create(() => new InfiniteReflectionActor()).WithDispatcher(disPacther),
                                                                                          actorSecondName));

                //무한전송을 위한,응답대상을 크로스로 연결및 무한메시지 시작
                infiniteReflectionActorA.Tell(infiniteReflectionActorB);
                infiniteReflectionActorB.Tell(infiniteReflectionActorA);

                for (int ballIdx = 0; ballIdx < ballCount; ballIdx++)
                {
                    infiniteReflectionActorA.Tell(new InfiniteMessage()
                    {
                        Message = "서브A",
                        Count   = 0
                    });
                }
            }
        }
Exemple #9
0
        public CashGateActor()
        {
            rnd    = new Random();
            id     = Guid.NewGuid().ToString();
            msgCnt = 0;
            logger.Info($"Create CashGateActor:{id}");
            CountConsume = AkkaLoad.ActorSelect("SingleToneActor");

            ReceiveAsync <DelayMsg>(async msg =>
            {
                msgCnt++;

                Context.IncrementMessagesReceived();
                Context.IncrementCounter("akka.custom.received1");

                logger.Info($"{msg.Message}--{msgCnt}");

                if (null != CountConsume)
                {
                    CountConsume.Tell(msg);
                }

                //정산 소요 시간
                int auto_delay = msg.Delay == 0 ? rnd.Next(300, 1000) : msg.Delay;
                await Task.Delay(auto_delay);

                //수신자가 있으면 보낸다.
                if (!Sender.IsNobody())
                {
                    if (msg.Message == "정산해주세요")
                    {
                        Sender.Tell($"정산완료 통과하세요");
                    }
                }
            });

            ReceiveAsync <StopActor>(async msg =>
            {
                Sender.Tell("Done");
                Context.Stop(Self);
            });
        }
Exemple #10
0
        public HighPassGateActor()
        {
            id = Guid.NewGuid().ToString();
            logger.Info($"Create HigPassGateActor:{id}");
            msgCnt            = 0;
            random            = new Random();
            MatrixSingleActor = AkkaLoad.ActorSelect("SingleToneActor");

            ReceiveAsync <DelayMsg>(async msg =>
            {
                if (MonitorMode)
                {
                    Context.IncrementMessagesReceived();
                }

                msgCnt++;

                int auto_delay = msg.Delay == 0 ? random.Next(1, 100) : msg.Delay;
                await Task.Delay(auto_delay);

                var completeMsg = new DelayMsg()
                {
                    State   = DelayMsgState.Completed,
                    Message = msg.Message,
                    Seq     = msg.Seq
                };

                MatrixSingleActor.Tell(completeMsg);

                if (MonitorMode)
                {
                    Context.IncrementCounter("akka.custom.received1");
                }

                logger.Info($"Msg:{msg.Message} Count:{msgCnt} Delay:{auto_delay}");
            });
        }
 public ActorTestController(ILogger <ActorTestController> logger, ActorSystem actorSystem)
 {
     _logger      = logger;
     throttleWork = AkkaLoad.ActorSelect("throttleWork");
     _actorSystem = actorSystem;
 }
Exemple #12
0
 public LoadTestController()
 {
     TPSCommandActor = AkkaLoad.ActorSelect("TPSCommandActor");
 }
Exemple #13
0
        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllers();

            services.AddSingleton(Configuration.GetSection("AppSettings").Get <AppSettings>());// * AppSettings

            services.AddSingleton <ConsumerSystem>();
            services.AddSingleton <ProducerSystem>();

            services.AddDbContext <UserRepository>();

            // Akka 설정
            // 참고 :  https://getakka.net/articles/concepts/configuration.html
            // AKKASYSTEM : http://wiki.webnori.com/display/AKKA/AKKASYSTEM
            // Akka 셋팅
            var envName    = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
            var akkaConfig = AkkaLoad.Load(envName, Configuration);

            actorSystem = ActorSystem.Create("AkkaDotBootSystem", akkaConfig);

            services.AddAkka(actorSystem);

            //모니터링추가
            var statsdConfig = new StatsdConfig
            {
                StatsdServerName = "127.0.0.1"
            };

            //ActorMonitoringExtension.RegisterMonitor(actorSystem, new ActorDatadogMonitor(statsdConfig));


            // Signal R 셋팅
            services
            .AddSingleton(new ConnectionSourceSettings(102400, OverflowStrategy.DropBuffer))
            .AddSignalRAkkaStream()
            .AddSignalR();

            // Swagger
            services.AddSwaggerGen(c =>
            {
                c.SwaggerDoc("v1", new OpenApiInfo
                {
                    Version        = "v1",
                    Title          = AppName,
                    Description    = $"{AppName} ASP.NET Core Web API",
                    TermsOfService = new Uri(CompanyUrl),
                    Contact        = new OpenApiContact
                    {
                        Name  = Company,
                        Email = "*****@*****.**",
                        Url   = new Uri(CompanyUrl),
                    },
                    License = new OpenApiLicense
                    {
                        Name = $"Document",
                        Url  = new Uri(DocUrl),
                    }
                });

                c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
                {
                    Name         = "Authorization",
                    Type         = SecuritySchemeType.ApiKey,
                    Scheme       = "Bearer",
                    BearerFormat = "JWT",
                    In           = ParameterLocation.Header,
                    Description  = "JWT Authorization header using the Bearer scheme."
                });

                c.AddSecurityRequirement(new OpenApiSecurityRequirement
                {
                    {
                        new OpenApiSecurityScheme
                        {
                            Reference = new OpenApiReference
                            {
                                Type = ReferenceType.SecurityScheme,
                                Id   = "Bearer"
                            }
                        },
                        new string[] {}
                    }
                });

                // Set the comments path for the Swagger JSON and UI.
                var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml";
                var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile);
                c.IncludeXmlComments(xmlPath);
            });
        }
Exemple #14
0
        static public void StartKafkaTest(IApplicationBuilder app, ActorSystem actorSystem)
        {
            // 기호에따라 사용방식이 약간 다른 KAFKA를 선택할수 있습니다.

            //##################################################################
            //##### Confluent.Kafka를 Akka액터 모드로 연결한 모드로
            //##### 보안연결이 지원하기때문에 Saas형태의 Kafka에 보안연결이 가능합니다.
            //##### 커스텀한 액터를 생성하여,AkkaStream을 이해하고 직접 연결할수 있을때 유용합니다.
            //##################################################################

            //ProducerActor
            var producerAkkaOption = new ProducerAkkaOption()
            {
                BootstrapServers = "webnori.servicebus.windows.net:9093",
                ProducerName     = "webnori-kafka",
                SecurityOption   = new KafkaSecurityOption()
                {
                    SecurityProtocol = SecurityProtocol.SaslSsl,
                    SaslMechanism    = SaslMechanism.Plain,
                    SaslUsername     = "******",
                    SaslPassword     = "******",
                    SslCaLocation    = "./cacert.pem"
                }
            };

            string producerActorName = "producerActor";
            var    producerActor     = AkkaLoad.RegisterActor(producerActorName /*AkkaLoad가 인식하는 유니크명*/,
                                                              actorSystem.ActorOf(Props.Create(() =>
                                                                                               new ProducerActor(producerAkkaOption)),
                                                                                  producerActorName /*AKKA가 인식하는 Path명*/
                                                                                  ));

            producerActor.Tell(new BatchData()
            {
                Data = new KafkaTextMessage()
                {
                    Topic   = "akka100",
                    Message = "testData"
                }
            });

            //ConsumerActor
            var consumerAkkaOption = new ConsumerAkkaOption()
            {
                BootstrapServers = "webnori.servicebus.windows.net:9093",
                Topics           = "akka100",
                AutoOffsetReset  = AutoOffsetReset.Earliest,
                KafkaGroupId     = "akakTestGroup",
                RelayActor       = null, //작업자 액터를 연결하면, 소비메시지가 작업자에게 전달된다 ( 컨슘기능과 작업자 기능의 분리)
                SecurityOption   = new KafkaSecurityOption()
                {
                    SecurityProtocol = SecurityProtocol.SaslSsl,
                    SaslMechanism    = SaslMechanism.Plain,
                    SaslUsername     = "******",
                    SaslPassword     = "******",
                    SslCaLocation    = "./cacert.pem"
                }
            };

            string consumerActorName = "consumerActor";
            var    consumerActor     = AkkaLoad.RegisterActor(consumerActorName /*AkkaLoad가 인식하는 유니크명*/,
                                                              actorSystem.ActorOf(Props.Create(() =>
                                                                                               new ConsumerActor(consumerAkkaOption)),
                                                                                  consumerActorName /*AKKA가 인식하는 Path명*/
                                                                                  ));

            //컨슈머를 작동시킨다.
            consumerActor.Tell(new ConsumerStart());

            //##################################################################
            //##### Akka.Streams.Kafka(의존:Confluent.Kafka) 을 사용하는 모드로, Security(SSL)이 아직 지원되지 않습니다.
            //##### Private으로 구성된, Kafka Pass 모드일때 사용가능합니다.
            //##### AkkaStream.Kafka가 제공하는 스트림을 활용핼때 장점이 있습니다.
            //##################################################################

            // KAFKA -
            // 각 System은 싱글톤이기때문에 DI를 통해 Controller에서 참조획득가능
            var consumerSystem = app.ApplicationServices.GetService <ConsumerSystem>();
            var producerSystem = app.ApplicationServices.GetService <ProducerSystem>();

            //소비자 : 복수개의 소비자 생성가능
            consumerSystem.Start(new ConsumerAkkaOption()
            {
                KafkaGroupId     = "testGroup",
                BootstrapServers = "kafka:9092",
                RelayActor       = null,    //소비되는 메시지가 지정 액터로 전달되기때문에,처리기는 액터로 구현
                Topics           = "akka100",
            });

            //생산자 : 복수개의 생산자 생성가능
            producerSystem.Start(new ProducerAkkaOption()
            {
                BootstrapServers = "kafka:9092",
                ProducerName     = "producer1",
            });

            List <string> messages = new List <string>();

            for (int i = 0; i < 10; i++)
            {
                messages.Add($"message-{i}");
            }

            //보너스 : 생산의 속도를 조절할수 있습니다.
            int tps = 10;

            producerSystem.SinkMessage("producer1", "akka100", messages, tps);
        }
Exemple #15
0
        public KafkaController(ProducerSystem _producerSystem)
        {
            producerSystem = _producerSystem;

            producerActor = AkkaLoad.ActorSelect("producerActor");
        }
Exemple #16
0
        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IApplicationLifetime lifetime)
        {
            app.UseSwagger();
            // Enable middleware to serve swagger-ui (HTML, JS, CSS, etc.),
            // specifying the Swagger JSON endpoint.
            app.UseSwaggerUI(c =>
            {
                c.SwaggerEndpoint("/swagger/v1/swagger.json", "My API V1");
            });

            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseRouting();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });

            MetricServer metricServer = null;
            var          appConfig    = app.ApplicationServices.GetService <AppSettings>();

            AppSettings = appConfig;


            //APP Life Cycle
            lifetime.ApplicationStarted.Register(() =>
            {
                app.ApplicationServices.GetService <ILogger>();

                var actorSystem = app.ApplicationServices.GetService <ActorSystem>(); // start Akka.NET
                ActorSystem     = actorSystem;

                //싱글톤 클러스터 액터
                actorSystem.BootstrapSingleton <SingleToneActor>("SingleToneActor", "akkanet");
                var singleToneActor = actorSystem.BootstrapSingletonProxy("SingleToneActor", "akkanet", "/user/SingleToneActor", "singleToneActorProxy");
                AkkaLoad.RegisterActor("SingleToneActor", singleToneActor);


                // ###########  로드 테스트 전용

                // 클러스터내 싱글톤은 하나만 존재할수있음 : akka.cluster.singleton  - akka.conf참고

                //액터 선택 : AkkaLoad.ActorSelect("ClusterWorkerPoolActor")
                var worker = AkkaLoad.RegisterActor(
                    "ClusterWorkerPoolActor",
                    actorSystem.ActorOf(Props.Create <ClusterWorkerPoolActor>()
                                        .WithDispatcher("fast-dispatcher")
                                        .WithRouter(FromConfig.Instance),
                                        "cluster-workerpool"
                                        ));

                //커멘드 액터( 로드테스트용)
                //액터생성
                AkkaLoad.RegisterActor(
                    "TPSCommandActor",
                    actorSystem.ActorOf(Props.Create <TPSCommandActor>(worker),
                                        "TPSCommandActor"
                                        ));

                // ###########  로드 테스트 전용


                //액터생성
                AkkaLoad.RegisterActor(
                    "basic",
                    actorSystem.ActorOf(Props.Create <BasicActor>(),
                                        "basic"
                                        ));

                // DI 연동
                AkkaLoad.RegisterActor(
                    "toner",
                    actorSystem.ActorOf(actorSystem.DI().Props <TonerActor>()
                                        .WithRouter(new RoundRobinPool(1)),
                                        "toner"
                                        ));

                AkkaLoad.RegisterActor(
                    "printer",
                    actorSystem.ActorOf(actorSystem.DI().Props <PrinterActor>()
                                        .WithDispatcher("custom-dispatcher")
                                        .WithRouter(FromConfig.Instance).WithDispatcher("custom-task-dispatcher"),
                                        "printer-pool"
                                        ));

                // DI 미연동
                AkkaLoad.RegisterActor(
                    "highpass",
                    actorSystem.ActorOf(Props.Create <HighPassGateActor>()
                                        .WithDispatcher("fast-dispatcher")
                                        .WithRouter(FromConfig.Instance),
                                        "highpass-gate-pool"
                                        ));

                AkkaLoad.RegisterActor(
                    "cashpass",
                    actorSystem.ActorOf(Props.Create <CashGateActor>()
                                        .WithDispatcher("slow-dispatcher")
                                        .WithRouter(FromConfig.Instance),
                                        "cashpass-gate-pool"
                                        ));

                AkkaLoad.RegisterActor(
                    "clusterRoundRobin",
                    actorSystem.ActorOf(Props.Create <ClusterPoolActor>()
                                        .WithDispatcher("fast-dispatcher")
                                        .WithRouter(FromConfig.Instance),
                                        "cluster-roundrobin"
                                        ));

                // 스트림 - 밸브조절액터
                int timeSec       = 1;
                var throttleActor = AkkaLoad.RegisterActor(
                    "throttleActor",
                    actorSystem.ActorOf(Props.Create <ThrottleActor>(timeSec)
                                        ));
                var throttleWork = actorSystem.ActorOf(Props.Create <ThrottleWork>(5, 1));
                throttleActor.Tell(new SetTarget(throttleWork));

                try
                {
                    var MonitorTool         = Environment.GetEnvironmentVariable("MonitorTool");
                    var MonitorToolCon      = Environment.GetEnvironmentVariable("MonitorToolCon");
                    var MonitorToolCons     = MonitorToolCon.Split(":");
                    string StatsdServerName = MonitorToolCons[0];
                    int StatsdPort          = 8125;
                    if (MonitorToolCons.Length > 1 && 10 > MonitorToolCons.Length)
                    {
                        StatsdPort = int.Parse(MonitorToolCons[1]);
                    }
                    switch (MonitorTool)
                    {
                    case "win":
                        var win = ActorMonitoringExtension.RegisterMonitor(actorSystem,
                                                                           new ActorPerformanceCountersMonitor(
                                                                               new CustomMetrics
                        {
                            Counters =
                            {
                                "akka.custom.metric1",   "akka.custom.metric2", "akka.custom.metric3",
                                "akka.custom.received1", "akka.custom.received2"
                            },
                            Gauges = { "akka.gauge.msg10", "akka.gauge.msg100", "akka.gauge.msg1000", "akka.gauge.msg10000" },
                            Timers = { "akka.handlertime" }
                        }));

                        // 윈도우 성능 모니터링 수집대상항목은 최초 Admin권한으로 akka항목으로 레지스트리에 프로그램실행시 자동 등록되며
                        // 커스텀항목 결정및 최초 1번 작동후 변경되지 않음으로
                        // 수집 항목 변경시 아래 Register 삭제후 다시 최초 Admin권한으로 작동
                        // Actor명으로 매트릭스가 분류됨으로 기능단위의 네이밍이 권장됨
                        // HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Akka\Performance
                        break;

                    case "azure":
                        var azure = ActorMonitoringExtension.RegisterMonitor(actorSystem, new ActorAppInsightsMonitor(appConfig.MonitorToolCon));
                        break;

                    case "prometheus":
                        // prometheusMonotor 를 사용하기위해서, MerticServer를 켠다...(수집형 모니터)
                        // http://localhost:10250/metrics
                        metricServer = new MetricServer(10250);
                        metricServer.Start();
                        var prometheus = ActorMonitoringExtension.RegisterMonitor(actorSystem, new ActorPrometheusMonitor(actorSystem));
                        break;

                    case "datadog":
                        var statsdConfig = new StatsdConfig
                        {
                            StatsdServerName = StatsdServerName,
                            StatsdPort       = StatsdPort
                        };
                        var dataDog = ActorMonitoringExtension.
                                      RegisterMonitor(actorSystem, new ActorDatadogMonitor(statsdConfig));
                        break;
                    }
                }
                catch (Exception e)
                {
                    Console.WriteLine("=============== Not Suport Window Monitor Tools ===============");
                }

                ActorMonitoringExtension.Monitors(actorSystem).IncrementDebugsLogged();
            });

            lifetime.ApplicationStopping.Register(() =>
            {
                Console.WriteLine("=============== Start Graceful Down ===============");
                var actorSystem = app.ApplicationServices.GetService <ActorSystem>();

                if (appConfig.MonitorTool == "prometheus")
                {
                    metricServer.Stop();
                }

                // Graceful Down Test,Using CashGateActor Actor
                AkkaLoad.ActorSelect("cashpass").Ask(new StopActor()).Wait();


                var cluster = Akka.Cluster.Cluster.Get(actorSystem);
                cluster.RegisterOnMemberRemoved(() => MemberRemoved(actorSystem));
                cluster.Leave(cluster.SelfAddress);
                asTerminatedEvent.WaitOne();

                Console.WriteLine($"=============== Completed Graceful Down : {cluster.SelfAddress} ===============");
            });
        }