Dispatcher는 ActorSystem 내에서 실행되는 모든 코드를 스케줄링을 하며

각 Actor의 처리량과 시간 점유율을 조정하여 각자에게 공정한 리소스를 제공합니다.

스케줄러방식을 복잡한 스레드 코드 구현이 아닌, 전략적인 설정화를 통해 구상할수가 있습니다.


Dispatcher의 탄생배경?

전통적인 개발방식에서 병렬처리를 통해 스케일업과 관련한 성능문제를

해결하였으며 고급적인 여러 스레드모델이 등장하여 동시성 경합문제등을

해결을 하였으나, 장비한대의 극한 성능을 올리기위해서 표준적이지 못한

스레드 프로그래밍의 개발방법으로 인해  서비스의 흐름보다

대용량 처리를위해 스레드를 얼마나 더 잘다루느냐?  흐름을 방해하는 요소가 되었습니다.

결정적으로 대용량 분산처리환경에서 이것은 큰 도움이 되지 못한다는것입니다.

스레드를 개발자가 각각 작성하는  코딩을 배제하고 스레드를 똑똑하게 관리하는

공통모듈을 ( Dispatcher ) 를두고 서비스코드에 집중하되, 튜닝요소는 환경설정으로

모두분리하자는 컨셉입니다. 

AKKA에서 처음등장한 개념은 아니며,  AKKA의 Dispatcher는 이러한 컨셉을 잘 준수하며

비동기처리에대한 튜닝장치로 사용될수 있습니다.

Dispatcher전략

  • 스레드풀을 분리해라 : 응답이 오래걸리는것과 아닌것을 분리함으로, 오래걸리는것을 별도로 스레드수를 확보할수가 있다.
  • 순차처리보다 병렬처리를 활용 : 한가지의 요청이 끝나기전 다른 요청이 진행될수 없는경우와 동시에 요청을한후 머징처리되는게 효율적인경우를 분리 
  • 최종전략 : 순차적으로 처리해야할것과 병렬적으로 처리해야할것이 썩일수 있으며 튜닝은 이것을 고려해야한다.

스레드 작동방식에 따른 전략

  • thread-pool-executor : 각 Task의 완료시간이 비슷할시 유용하지만 전체완료시간을 줄이는데 기여하지는 못함, 빠른 Task가 모두 완료될시 놀고있는 스레드가 생길수가 있다. 동시성 병렬처러 프로그래밍 모델에 일반적으로 활용되는 모델임
  • fork-join-executor : 각 Task의 완료시간이 차이가 있을시 유용하며 전체 완료시간을 줄이는데 목표로함, 놀고 있는 스레드의 자원 가져다가 활용할수있다. 동시성 비동기 프로그래밍모델에서 일반적으로 활용되는 모델임


참고 자바이슈 : http://hamait.tistory.com/612


Dispatcher Option

  • parallelism-min = 2 : 동시에 활성화되는 최소 스레드수 (available processors * factor)
  • parallelism-max = 8 : 동시에 활성화되는 최대 스레드수
  • parallelism-factor = 2.0 : Core개수대비 최대가 될수있는 스레드수
  • throughput = 100 : 동시에 처리하는 메시지수
  • fixed-pool-size = 32 : 스레드 개수 고정

Dispatcher 설정 샘플

akka {
	loggers = ["akka.event.Logging$DefaultLogger"]
	loglevel = "INFO"
	stdout-loglevel = "ERROR"	
}

blocking-io-dispatcher {
	type = Dispatcher
	executor = "thread-pool-executor"
	thread-pool-executor {
	fixed-pool-size = 2
	}
	throughput = 1
}

my-thread-pool-dispatcher {
  # Dispatcher is the name of the event-based dispatcher
  type = Dispatcher
  # What kind of ExecutionService to use
  executor = "thread-pool-executor"
  # Configuration for the thread pool
  thread-pool-executor {
    # minimum number of threads to cap factor-based core number to
    core-pool-size-min = 2
    # No of core threads ... ceil(available processors * factor)
    core-pool-size-factor = 2.0
    # maximum number of threads to cap factor-based number to
    core-pool-size-max = 10
  }
  # Throughput defines the maximum number of messages to be
  # processed per actor before the thread jumps to the next actor.
  # Set to 1 for as fair as possible.
  throughput = 100
}
	
my-dispatcher {
  # Dispatcher is the name of the event-based dispatcher
  type = Dispatcher
  # What kind of ExecutionService to use
  executor = "fork-join-executor"
  # Configuration for the fork join pool
  fork-join-executor {
    # Min number of threads to cap factor-based parallelism number to
    parallelism-min = 2
    # Parallelism (threads) ... ceil(available processors * factor)
    parallelism-factor = 2.0
    # Max number of threads to cap factor-based parallelism number to
    parallelism-max = 10
  }
  # Throughput defines the maximum number of messages to be
  # processed per actor before the thread jumps to the next actor.
  # Set to 1 for as fair as possible.
  throughput = 100
}

(lightbulb) AKKA는 자바가 가진 스레드 모델에따른 스케쥴러를 정확하게 이해하고 이것을 추상화하여 성능 튜닝요소로 활용을 합니다.

이것은 AKKA를 배워야하는 이유중 일부분입니다. 모던한 개발툴킷들은 대부분 전통적인 개발방식의 문제를 해결하기위해

스레드 작성을 직접하지 말것을 권장합니다. 툴킷자체가 스레드를 어떻게 잘 다룰지 알고있으며 심지어 이것을 우리가

알고있는것보다 더 자세하게 설명하고 효율적으로 안정적으로 사용할수 있는 가이드(구속복)를 제공합니다.


동시처리 스레드 제한 예제

//application.conf 설정
blocking-io-dispatcher {
 type = Dispatcher
 executor = "thread-pool-executor"
 thread-pool-executor {
 fixed-pool-size = 2
 }
 throughput = 1
}


//구현부
//특정 액터 Dispatcher지정
ActorRef testActor = system.actorOf(ext.props("testActor")
 .withDispatcher("blocking-io-dispatcher"),
 "service1");


// 동시에 메시지 전송
for(int i=0;i<10;i++)
 testActor.tell("test message wiht dispatcher",null);

[INFO] [05/06/2018 23:27:21.795] [AkkaTestApp-blocking-io-dispatcher-8] [TestActor] Incommessage test message wiht dispatcher
[INFO] [05/06/2018 23:27:21.798] [AkkaTestApp-blocking-io-dispatcher-9] [TestActor] Incommessage test message wiht dispatcher
[INFO] [05/06/2018 23:27:21.799] [AkkaTestApp-blocking-io-dispatcher-8] [TestActor] Incommessage test message wiht dispatcher
[INFO] [05/06/2018 23:27:21.800] [AkkaTestApp-blocking-io-dispatcher-8] [TestActor] Incommessage test message wiht dispatcher
[INFO] [05/06/2018 23:27:21.801] [AkkaTestApp-blocking-io-dispatcher-8] [TestActor] Incommessage test message wiht dispatcher
[INFO] [05/06/2018 23:27:21.801] [AkkaTestApp-blocking-io-dispatcher-8] [TestActor] Incommessage test message wiht dispatcher
[INFO] [05/06/2018 23:27:21.802] [AkkaTestApp-blocking-io-dispatcher-8] [TestActor] Incommessage test message wiht dispatcher
[INFO] [05/06/2018 23:27:21.807] [AkkaTestApp-blocking-io-dispatcher-8] [TestActor] Incommessage test message wiht dispatcher
[INFO] [05/06/2018 23:27:21.807] [AkkaTestApp-blocking-io-dispatcher-8] [TestActor] Incommessage test message wiht dispatcher
[INFO] [05/06/2018 23:27:21.807] [AkkaTestApp-blocking-io-dispatcher-8] [TestActor] Incommessage test message wiht dispatcher

동시처리수를 1개로 제한하고, 스레드수를 2개로 제한을하면 스레드모델중 세마포어와 유사한 스레드풀 기능을 수행하게 되며

스레드모델 이용시 가장 심플하게 사용할수 있는 방법중 하나입니다. 동시 요청이 10개가 왔다고하면, 스레드 두개만 활용하여

분배되어 처리되게 됩니다. 이것은 한가지예일뿐이며, Dispatcher옵션으로 다양한 스레드모델의 효과를 볼수가 있습니다.


자바가가진 스레드풀의 개념과, 이를 더 추상화해주는 dispatcher에 대한 더 자세한것은

더 자세한것은 아래 URL을 통해 살펴볼수 있습니다.





  



  • No labels
Write a comment…