Versions Compared

Key

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

Akka에서의 분산처리 클러스터의 최종 목표는, 외부 클러스터 시스템을 이용만 하는것이 아닌

단일지점 병목지점이 없는 확장가능한 시스템을 구현하는것입니다.

구현한 클러스터 시스템을 실제 운영하는것은 다른 문제이나, 클러스터 시스템을 이용하는데 있어서도 도움이 될것입니다.

Table of Contents

클러스터 분산처리

클러스터는 여러 대의 컴퓨터들이 연결되어 하나의 시스템처럼 동작하는 컴퓨터들의 집합을 말하며

...

git : https://github.com/psmon/AkkaForNetCore/tree/master/LightHouse

클러스터 OverView

Gossip Protocol

단일지점 병목을 없애기위해 피어투 프로토콜을 이용하며, 각노드는 빠르게 특정대상(정확히는 구성된 라우터)에게 이야기할수 있으며

...

Expand
title라우팅 종류

Include Page
AKKA:라우팅 전략Routing strategy
AKKA:라우팅 전략Routing strategy


클러스터 탑재하기

설정

Code Block
akka {
	remote {
		log-remote-lifecycle-events = debug
        dot-netty.tcp {
            port = 7000
			hostname = 127.0.0.1
		}
    }

	actor {
		provider = cluster
		deployment {
			/cluster-roundrobin {
				router = round-robin-pool # routing strategy
				#routees.paths = ["/user/clustermsg"]
				nr-of-instances = 500 # max number of total routees
				cluster {
					enabled = on
					allow-local-routees = on
					use-role = akkanet
					max-nr-of-instances-per-node = 20
				}
			}
		}
	}

	cluster {
        seed-nodes = ["akka.tcp://actor-cluster@127.0.0.1:7100"] # address of seed node
        roles = ["akkanet"] # roles this member is in
        auto-down-unreachable-after = 300s
		debug {
			verbose-heartbeat-logging = off
			verbose-receive-gossip-logging = off
		}
    }
}

...

  • actor.privider = cluster : 해당 액터들을 클러스터로 사용하겠다.
  • cluster-roundrobin.cluster.user-role = 롤이름 : 라운드 로빈방식으로, 롤 이름으로 지정된 노드에서 작동됨
  • cluster.seed-nodes : 등대역활 지정
  • cluster.roles : 자신이 가져야할 롤 지정(복수개지정가능)

로컬액터 클러스터액터로 전환

Code Block
protected Cluster Cluster = Akka.Cluster.Cluster.Get(Context.System);
private bool ClusterMode = true;

protected override void PreStart()
{
	// subscribe to IMemberEvent and UnreachableMember events
	if (ClusterMode)
	{
		Cluster.Subscribe(Self, ClusterEvent.InitialStateAsEvents,
		new[] { typeof(ClusterEvent.IMemberEvent), typeof(ClusterEvent.UnreachableMember) });
	}
}

protected override void PostStop()
{
	if (ClusterMode) Cluster.Unsubscribe(Self);	
}
// src : https://github.com/psmon/AkkaForNetCore/blob/master/AkkaNetCore/Actors/ClusterMsgActor.cs

...

도메인 메시지를 처리하는 Received에는 코드변화가 없습니다.


클러스터로 구성된 액터에게 메시지 보내기

Code Block
// 클러스터 액터 설정 : https://github.com/psmon/AkkaForNetCore/blob/master/AkkaNetCore/Startup.cs

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

// 클러스터 액터 DI 참조 얻기및 메시지 보내기  : https://github.com/psmon/AkkaForNetCore/blob/master/AkkaNetCore/Controllers/ActorTestController.cs
			
private readonly IActorRef clusterRoundbin1;
public ActorTestController()
{            
	clusterRoundbin1 = AkkaLoad.ActorSelect("clusterRoundRobin");
}

[HttpPost("/cluster/msg/tell")]
public void ClusterMsg(string value, int count)
{
	for (int i = 0; i < count; i++)
		clusterRoundbin1.Tell(value);
}

클러스터 한방에 로컬에서 뛰우기

클러스터 개발의 난제는, 로컬에 구성요소를 N개를 뛰우고 디버깅이 가능한가인데, 도커가 없을 시절

...

Code Block
titledocker-compose.yml
collapsetrue
version: '3.4'

services:
  datadog:
    image: datadog/agent:7
    ports:
      - 8125/udp
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - /proc/:/host/proc/:ro
      - /sys/fs/cgroup/:/host/sys/fs/cgroup:ro
    environment:
      DD_API_KEY: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
      DD_DOGSTATSD_NON_LOCAL_TRAFFIC: "true"

  lighthouse:
    image: ${DOCKER_REGISTRY-}lighthouse
    build:
      context: .
      dockerfile: LightHouse/Dockerfile
    environment:
      CLUSTER_IP: lighthouse
      CLUSTER_PORT: 4053
      CLUSTER_SEEDS: akka.tcp://actor-cluster@lighthouse:4053

  akkanetcore:
    image: ${DOCKER_REGISTRY-}akkanetcore
    build:
      context: .
      dockerfile: AkkaNetCore/Dockerfile
    depends_on:
     - lighthouse
    ports:
     - 8080:5000
    environment:
      ASPNETCORE_ENVIRONMENT: Development
      MonitorTool: datadog
      MonitorToolCon: datadog
      port: 5000
      akkaport: 7100
      akkaip: akkanetcore
      roles: "akkanet"
      akkaseed: "akka.tcp://actor-cluster@lighthouse:4053"

  akkanetcore2:
    image: ${DOCKER_REGISTRY-}akkanetcore
    build:
      context: .
      dockerfile: AkkaNetCore/Dockerfile
    depends_on:
     - lighthouse    
    environment:
      ASPNETCORE_ENVIRONMENT: Development
      MonitorTool: datadog
      MonitorToolCon: datadog
      port: 5000
      akkaport: 7000
      akkaip: akkanetcore2
      roles: "akkanet"
      akkaseed: "akka.tcp://actor-cluster@lighthouse:4053"

  akkanetcore3:
    image: ${DOCKER_REGISTRY-}akkanetcore
    build:
      context: .
      dockerfile: AkkaNetCore/Dockerfile
    depends_on:
     - lighthouse    
    environment:
      ASPNETCORE_ENVIRONMENT: Development
      MonitorTool: datadog
      MonitorToolCon: datadog
      port: 5000
      akkaport: 7000
      akkaip: akkanetcore3
      roles: "akkanet"
      akkaseed: "akka.tcp://actor-cluster@lighthouse:4053"


데이터 분산처리

이 샘플에서는, 메시징을 별도로 저장하지 않았으며  처리중인 메시지는 영속화를 할수가 있습니다.

...