Versions Compared

Key

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

스냅샷은 액터의 복구속도를 높일수가 있습니다.

SaveSnapShot을 호출하여 내부상태의 스냅샷을 저장할수가 있습니다.


나의 마지막상태, 예를 들면 내가 마지막에 본 페이지를 서비스가 기록을 하고 다른기기를 옮겨가도 

그 상태를 복구하여 그대로 보여줄수 있는 서비스가 있다고 가정해봅시다. 사용자가 페이지를 이동할때마다

전통적인 개발방법은 메인 DB에 기록을 할것이며, 메인 DB에 부하를 주게될것입니다. 어쨋든 어플리케이션은

종료가 되거나 재시작이 될수 있으니까요, 액터의 스냅샷을 이용하면 자신이 원하는 타이밍에 원하는

로컬 스토리지에 저장을하고 마지막 상태를 완벽하게 복원할수가 있습니다. 여기서 원하는 타이밍은

페이지 이동에따른 비용이아닌, 만약 초당 100건이상의 메시지가 발생한다라고 가정해봅시다. 이 모든타이밍에

스냅샷에 기록할수도 있겠지만 낭비적입니다. 그렇게 저장할만큼 중요한 기능은 아니기때문에

이러한 경우 스냅샷 시기를 느슨하게 하여 어쨋든 장애로인한 재시작 이후 마지막에 저장한 스냅샷을 복구해줄것입니다.

액터설계

Code Block
languagec#
themeEmacs
linenumberstrue
public class MySnapShotActor : UntypedPersistentActor
{
    private ILoggingAdapter log = Context.GetLogger();
    public override string PersistenceId => "my-stable-persistence-id";
    private const int SnapShotInterval = 2; //2의 배수에 스냅샷을 저장합니다.
    private object state = new object();

    //실시간 복구수 전략을 선택합니다. (최근5개)
    public override Recovery Recovery => new Recovery(fromSnapshot: new SnapshotSelectionCriteria(minSequenceNr:0, maxSequenceNr: 5, maxTimeStamp: DateTime.UtcNow));
    //public override Recovery Recovery => new Recovery(fromSnapshot: SnapshotSelectionCriteria.Latest);

    protected override void OnRecover(object message)
    {
        // handle recovery here
        if (message is SnapshotOffer offeredSnapshot)
        {
            log.Debug("마지막 스냅샷 복구");
            state = offeredSnapshot.Snapshot;
            log.Debug("스냅샷복구완료:" + state);
        }
        else if (message is RecoveryCompleted)
        {
            log.Debug("스냅샷복구완료:");
        }
        else
        {
            // event
            log.Debug("스냅샷e:" + message);
        }
    }

    protected override void OnCommand(object message)
    {
        if (message is SaveSnapshotSuccess s)
        {
            log.Debug("스냅샷 성공");
        }
        else if (message is SaveSnapshotFailure f)
        {
            log.Debug("스냅샷 실패");
        }
        else if (message is string cmd)
        {
            log.Debug("cmd:" + cmd);
            Persist($"evt-{cmd}", e =>
            {
                UpdateState(e);
                if (LastSequenceNr % SnapShotInterval == 0 && LastSequenceNr != 0)
                {
                    log.Debug("스냅샷 시도");
                    SaveSnapshot(state);
                }
            });
        }
    }

    private void UpdateState(string evt)
    {
        state = evt;
    }
}

...