Versions Compared

Key

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

...

  • AbstractBehavior를 상속받는 일반적인 TypedActor를 생성합니다.
    • 지정되는 템플릿은 처리가능한 이벤트 유형입니다.처리가능 이벤트 유형을 나타내며~ Classic Actor에 비해 Typed제약 이벤트만을 처리 하기때문에 컴파일 타임시 처리하지 못하는 메시지 오류를 검출합니다.
    • 오류를 찾는것뿐만 아니라 Typed Actor의 경우 발생한 이벤트가 어떠한 액터가 처리하는지? 코드레벨에서 추적도 가능하게 됩니다. 
      • Untyped의 경우 IDE단계에서 함수추적하듯 코드추적이 안되며 수신받는 액터의 이벤트 리슨부분의  케이스패턴 코드를 살펴봐야합니다. 

전체 코드 : https://github.com/psmon/kopring-reactive-labs/tree/main/KotlinBootReactiveLabs/src/main/kotlin/org/example/kotlinbootreactivelabs/actor

...

독립구성되고 분리된 영역에서 작동되며 자바 비동기처리 활용하면서 상호연동될수 있습니다. 초반 구성하는것에 다소 손이 많이가 초기 셋팅과정에 난이도가 있지만 이제 클러스터에서 유용한 장치들을 몇가지 살펴보겠습니다많이가고  초기구성에 성공하고 몇가지 장치를 이해하면

클러스터된 시스템을 단지 이용하는것이아니~ 구성된 클러스터내에서 액터를 중심으로 분산처리에 이용되는 기능들을 단순화해 활용할수 있습니다.


SigleTone Cluster

단일 어플리케이션에서 단 하나만 작동시켜야하는 싱글톤 패턴을 이용하는 DI는 유용합니다. 단일 시스템내에서 단하나만 작동하기때문입니다.

...

  • ActorTestKit은 유닛테스트 환경에서 AkkaSystem의 환경을 동일하게 구동합니다. 
  • 설정파일을 통해 각각 다른 역할을 수행하는 멀티노드를 구성할수 있게됩니다.
  • 유닛테스트 작성을 "시간이 없어서~ 유용하지않아서" 라고 이야기하곤 합니다.
    • 우리가 만든기능이 분산되었을때  단일지점에서 유닛테스트를 수행 할수 "있느냐? 없느냐?" 의 문제입니다. 

유닛테스트 코드작성

Code Block
themeEmacs
    @Test
    fun testSingleCluster(){

        var givenInItCount = 5

        val testProbe = nodeA.createTestProbe<CounterState>()
        val testProbe2 = nodeB.createTestProbe<CounterState>()

        val sigleton1:ClusterSingleton = ClusterSingleton.get(nodeA.system())

        var proxy1:ActorRef<CounterCommand> = sigleton1.init(SingletonActor.of(CounterActor.create("singleId"), "GlobalCounter"))

        val sigleton2:ClusterSingleton = ClusterSingleton.get(nodeB.system())

        var proxy2:ActorRef<CounterCommand> = sigleton2.init(SingletonActor.of(CounterActor.create("singleId"), "GlobalCounter"))

        proxy1.tell(Increment(3))

        proxy1.tell(GetCount(testProbe.ref()))

        testProbe.expectMessage(CounterState(3 + givenInItCount))

        proxy2.tell(Increment(2))

        proxy2.tell(GetCount(testProbe2.ref()))

        testProbe2.expectMessage(CounterState(5 + givenInItCount))
    }

...

아래 코드를 통해  샘플클라이언트를 통해 기능작동 확인을 할수 있으며 유닛테스트도 포함되어 있습니다.

Refrence :

이 장치는 redis 의 pub/sub 에 대응하며 해당장치와 연동하거나 대체할수도 있습니다. 

ExacltlyOnce Delivery

Akka의 Actor 메시지전송은 기본적으로 AtMostOnce 로 동작합니다. 전송보장을 위해 별도 설계를 할수도 있겠지만

중요 도메인 이벤트인경우 Kafka와 연동하는것을 권장하며 Reactive Stream(AkkaStream)을 통해 액터모델은 외부장치와 연결해

다양한 Consumer 전략을 선택할수 있습니다.

Link :


At-Most-Once Delivery란?

  • 메시지가 최대 한 번만 전달됨을 보장합니다.
  • 네트워크 장애 또는 기타 원인으로 인해 메시지가 손실될 수 있음.
  • 메시지 중복이 발생하지 않음.
  • 성능이 가장 우수하지만, 신뢰성이 낮음.
  • 손실이 허용되는 경우
    • 예: 모니터링 시스템(일부 로그 손실이 치명적이지 않음)
    • 예: 게임 로직에서의 이벤트(일시적인 위치 업데이트)
  • 고성능이 중요한 경우
    • ACK 기반 재전송이 필요 없기 때문에 메시지 처리 속도가 중요할 때 사용
  • 데이터가 중요하지 않거나, 외부에서 보완할 수 있는 경우
    • 예: UI 알림 전송 (사용자가 새로고침하면 다시 불러올 수 있음)

At-Most-Once 방식의 메시지 손실 문제를 보완하기 위해 다음과 같은 방법을 고려할 수 있음.

  1. At-Least-Once Delivery

    • 재전송을 통해 메시지 전달을 보장하지만, 중복이 발생할 수 있음.
    • Akka에서는 ask 패턴 또는 Akka Persistence(이벤트 소싱) 사용.
  2. Exactly-Once Delivery

    • 중복 제거 로직을 추가하여 메시지가 정확히 한 번만 처리되도록 보장.
    • Kafka 등의 외부 메시지 브로커와 조합하여 구현.
  3. Akka Reliable Delivery 사용

    • Akka의 Reliable Delivery 기능을 활용하면 At-Least-Once 또는 Exactly-Once 보장을 구현할 수 있음.


마치며

개인적으로 이 프로젝트를 팀에 활용하기위해 연구하는것은 다음 목표에 있습니다.

  1. Spring Boot이 주는 기본 Stack만으로도 고성능처리를 하기위해 부족함이 없습니다. 그래서 기본기가 가장중요합니다.
  2. 액터모델 부분 채택
    1. Akka의 채택은 SpringBoot Reacrive Adapter가 하지못하는 나머지 영역입니다.
    2. 전통적으로 웹진영에서 발전해혼 SteteLess기법만으로 대용량을 처리하는 경우 PasS의 의존도가 높아질수 있습니다.
    3. SteateFul 기법은 대용량 처리시 난이도가 있을수 있지만 비용절감 기법중 하나가 될수 있는 무기가 될수 있습니다.
    4. 액터모델은 StateFul 개발기법을 분산처리에 도입하고자할때 복잡성을 줄여주는 다양한 툴킷을 제공합니다.
  3. 외부장치 연동 ( kafka, mq...,nosql)
    1. 외부장치를 단순하게 풀링으로 이용하는것이아닌 stream으로 연동되어 상호 작동하는 인터페이스가 reactive stream으로 크게 성공한 활동입니다.
    2. reactive stream을 주도했던 기업이 akka를 만든 라이트벤드사 이며 akka가 아니여도 되지만, akka stream은  reactive stream을 준수하는 모든 장치와 고수준으로 연동하는 장치를 제공합니다.
      1.  https://learn.microsoft.com/ko-kr/azure/event-hubs/event-hubs-kafka-akka-streams-tutoria
        1. MS에서 자바 특정 프레임워크 akka 연동을 공식문서에 언급하는것은 이례적입니다. 
    3. akka가 아니여도되지만 액터모델과 연동되는 cqrs의 장치를 적어도 사용하고 작동시킬수 있음으로 이해를 시작 할수 있습니다. crud로만으로 오늘날의 대용량 트래픽을 커버할수 없으며 모든 샘플과 이론은 액터를 중심으로한 cqrs기법이 설명됩니다.
  4. 그동안 클라우드를 이용한던 웹진영의 StateLess 개발방식의 변화
    1. PasS에 의존하해 클라우드 클러스터를 활용하는것이 개발속도가 분명 가장 빠릅니다.


    2. 하지만 오늘날의 달러환률에 따른 클라우드 상승에따라 , 클라우드제공 시스템만을 사용하기에는 인프라비용을 최소화해야하는 오늘날의 개발팀에서 부담으로 다가옵니다.

    3. 단일지점 병목을 분산된 어플리케이션이 나눠서 처리하는 것이 akka 시스템의 목표이며 ec2의 비용은 저렴합니다. 저렴한 장치의 연산이용을 높이고 값비싼 단일지점 DB의 비용을 줄이는 전략은 앞으로 빠른개발을 위해 PasS를 만을 채택했던 개발기업이 트래픽 증가당 이익을 내기위해서는 클라우드 장치에만 의존하지않고 , 설계된 장치를 함께 운영하는 하이브리드 전략을 사용할것으로 예상합니다.
      1. aws 의 sqs는 매력적이지만 예측불가한 호출당 비용을 IT비용부서에서는 좋아하지 않습니다. 월과금이 일정한 kafka장치를 채택하거나 필요하면 온프레미스로 운영할수도 있으며 일부장치는 이미 존재하는 어플리케이션이 분산처리를 분담할수 있습니다.


새로운 패러다임의 개발패턴을 적용한다고하면  유닛테스트를 통해 설명가능하고 작동가능한 코드를 먼저 작성하는것이 권장되며

이 변종실험이 어떠한 팀에는 도움되는 장치가 되었으면 하는 오픈소스 마인드로

여기서 설명되는 모든 코드의 유닛테스트 코드를 함께 공유합니다. 

Refrences: