전자책 출간 알림 [마이크로서비스패턴 쉽게 개발하기]

티스토리 뷰

마이크로서비스 패턴 중  Event Sourcing 패턴에서 Event Replay의 속도를 높이는 방법으로 Snapshot을 얘기 했었습니다. 

[마이크로서비스 패턴 쉽게 개발 1] 마이크로서비스 패턴 이해: Saga, Event Sourcing, API Composition, CQRS

위 글 내용 중 '통장계좌'서비스 예를 들어 'Snapshot'을 얘기 했던게 기억 나실 겁니다.  

동일 주문에 대해 발생하는 Event수가 그리 많지 않아 Event Replay시간이 많이 걸리지는 않을 겁니다.
그런데 '통장계좌'서비스를 생각해 봅시다. 
통장을 개설하고 각 통장마다 발생하는 Event수는 엄청나게 많을 것입니다. 
예를 들어 한 통장에 1달에 보통 100건의 입출금 Event가 발생했고 
10년(120개월)을 사용했다면 총 Event의 수는 12,000건이 됩니다.
12,001번째 입금 Event가 발생했을때 최종 잔금을 계산하려면 
12,000번의 Event Replay를 해야 되겠죠. 
그래서 Event Replay의 성능을 향상시키기 위해 'Snapshot'을 사용합니다. 
일정 Event 갯수나 일정 시간마다 최종 데이터 상태를 'Snapshot'저장소에 기록하고, 
그 이후 발생한 Event들만 Replay를 하는 것입니다. 
위 통장의 예에서 10건마다 Snapshot을 저장했다면 최대 Replay할 Event의 갯수는 10개밖에 안될것입니다.

아래 그림은 Snapshot이 Event Replay에 어떻게 활용 되는지를 잘 보여주고 있습니다. 

[출처] https://cla9.tistory.com/12

우리가 실습하고 있는 '코끼리 냉장고 넣기' 서비스도 같은 코끼리를 계속 냉장고에 넣다 꺼냈다를 반복 할 수록 Event Replay의 횟수는 계속 늘어 납니다. 

그럼 Snapshot을 이용해서 이 Event Replay의 횟수를 줄여 속도를 높여 보겠습니다. 


Axon Framework은 아주 쉽게 Snapshot 기능을 이용할 수 있도록 지원 합니다. 

딱 두가지 작업만 하시면 됩니다. 

  • Snapshot Configuration 
  • Aggregate에 사용할 Snapshot 설정 명시 

Snapshot Configuration 

Snapshot Configuration은 AxonConfig class에서 하면 됩니다. 

추가된 2개 메소드가 Snapshot 설정입니다. 

package org.axon.config;

import com.thoughtworks.xstream.XStream;
import org.axonframework.common.caching.Cache;
import org.axonframework.common.caching.WeakReferenceCache;
import org.axonframework.eventsourcing.EventCountSnapshotTriggerDefinition;
import org.axonframework.eventsourcing.SnapshotTriggerDefinition;
import org.axonframework.eventsourcing.Snapshotter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class AxonConfig {
    @Bean
    public XStream xStream() {
        XStream xStream = new XStream();

        xStream.allowTypesByWildcard(new String[] {
                "org.axon.**"
        });
        return xStream;
    }

    @Bean
    public SnapshotTriggerDefinition snapshotTrigger(Snapshotter snapshotter) {
        return new EventCountSnapshotTriggerDefinition(snapshotter, 3);
    }

    @Bean
    public Cache snapshotCache() {
        return new WeakReferenceCache();
    }
}

 

EventCountSnapshotTriggerDefinition(snapshotter, {Event갯수}): 몇 개의 Event마다 Snapshot 저장소에 기록할 것인지 명시 

@Bean
public SnapshotTriggerDefinition snapshotTrigger(Snapshotter snapshotter) {
    return new EventCountSnapshotTriggerDefinition(snapshotter, 3);
}

 

Aggregate가 Event Replay를 하기 위해서는 각 Event마다 매번 Event Store를 접근하여 데이터를 읽어야 합니다. 이 방식은 매우 비효율적이고 속도도 느립니다. 

아래 설정은 Event Store의 데이터를 메모리에 로딩하여 Event Replay가 메모리 내에서 이루어 지도록 바꿉니다. 

@Bean
public Cache snapshotCache() {
    return new WeakReferenceCache();
}

 


Aggregate에 Snapshot 명시

ElephantAggregate의 @Aggregate 어노테이션의 파라미터로 지정 합니다. 

아래와 같이 기존 @Aggregate에 Snapshot 파라미터를 지정 합니다. 

@Slf4j
//@Aggregate
@Aggregate(snapshotTriggerDefinition = "snapshotTrigger", cache="snapshotCache")
public class ElephantAggregate {
    @AggregateIdentifier
    private String id;
...

테스트

어플리케이션을 재 시작하고 Swagger 페이지에서 코끼리 넣기 / 꺼내기를 반복해 보십시오.

콘솔의 로그를 보면 Snapshot을 사용하기 때문에 Event Replay의  횟수가 현저히 줄어 든것을 확인할 수 있습니다. 

위에서 Snapshot을 만들 Event갯수를 3개로 했기 때문에 최대 3개까지만 Replay됩니다.

(마지막 Event는 Replay되는게 아니라 새로운 요청이 처리된 결과 이벤트가 Event Store에 기록되는 로그입니다.  

[@EventSourcingHandler] EnteredElephantEvent for Id: 468
 ======== [넣기] Event Replay => 코끼리 상태: Exit
 ======== [넣기] 최종 코끼리 상태: Enter
 [@EventHandler] EnteredElephantEvent for Id: 468
 [@EventSourcingHandler] EnteredElephantEvent for Id: 468
 ======== [넣기] Event Replay => 코끼리 상태: Exit
 ======== [넣기] 최종 코끼리 상태: Enter
 [@EventSourcingHandler] ExitedElephantEvent for Id: 468
 ======== [꺼내기] Event Replay => 코끼리 상태: Enter
 ======== [꺼내기] 최종 코끼리 상태: Exit
 [@EventSourcingHandler] EnteredElephantEvent for Id: 468
 ======== [넣기] Event Replay => 코끼리 상태: Exit
 ======== [넣기] 최종 코끼리 상태: Enter

 

이 외에도 AxonIQ 가이드 문서에는 병렬처리와 처리 Thread를 늘리는 방법이 안내되고 있습니다. 

하지만 매뉴얼이 너무 빈약하여 실제 사용하려면 많은 시행 착오를 거쳐야 할 듯 합니다. 

미리 학습 또는 실무 경험이 있으신 분들은 공유해 주시면 감사하겠습니다. 

https://docs.axoniq.io/reference-guide/axon-framework/events/event-processors/streaming#token-stealing

 

Streaming Event Processors - Axon Reference Guide

All combined, the Streaming Processor allows for decoupling, parallelization, resiliency, and replay-ability. It is these features that make the Streaming Processor the logical choice for the majority of applications. Due to this, the "Tracking Event Proce

docs.axoniq.io

 


다음 편은 Aggregate의 특수한 형태인 State Stored Aggregate에 대해 배우겠습니다. 


마이크로서비스 패턴 쉽게 개발하기 목차

  1. 마이크로서비스 패턴 이해: Saga, Event Sourcing, API Composition, CQRS 이해
  2. 실습환경 준비
  3. 주문 서비스 테스트 
  4. Axon Framework 이해 
    1. 코끼리 냉장고에 넣기 프로젝트 시작
    2. CommandGateway와 Event Sourcing
    3. EventGateway
    4. QueryGateay
    5. Snapshot
    6. State Stored Aggregate
    7. Event Replay로 조회DB 데이터 복구

아래 주제들은 '마이크로서비스패턴 쉽게 개발하기'라는 제 책에서 만나실 수 있습니다. 

  • 멀티 모듈 프로젝트 작성
  • 신규 주문 정상처리 프로세스 구현 
  • 배송 상태 변경 및 재고 증감 처리
  • 신규 주문 보상처리 프로세스 구현
  • 주문 수정 정상처리 프로세스 구현
  • 주문 수정 보상처리 프로세스 구현
  • 주문 삭제 정상처리 프로세스 구현
  • 주문 삭제 보상처리 프로세스 구현
  • API Composition 패턴과 CQRS 패턴

책 한번 내겠다는 평소의 꿈을 실현하기 위해 이번에 전자책을 내게 되었습니다. 

제 꿈을 응원하신다는 마음으로 전체 내용을 공유하지 않는것을 양해해 주시고 

구매까지 해 주시면 더욱 감사하겠습니다. 

https://happycloud-lee.tistory.com/notice/291

 

[마이크로서비스패턴 쉽게 개발하기] 전자책 출간

안녕하세요? 온달입니다. 그동안 몇 번 시도하다 포기했던 책내기에 드디어 성공 했습니다. 책 제목은 '마이크로서비스패턴 쉽게 개발하기'입니다. 2024년 2월 19일 부터 교보문고, Yes24, 알라딘 등

happycloud-lee.tistory.com

 

댓글

전자책 출간 알림 [마이크로서비스패턴 쉽게 개발하기]