Versions Compared

Key

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

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

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

다음과 같은 메시지액터를 설계한다고 합시다.

...



...

액터설계

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;
    }
}


Test 시나리오

  • 단순하게 문자열 메시지만 전송받습니다.
  • 액터가 종료되더라도 최근 50개의 메시지를 복구합니다.
  • 테스트코드에서는 100개의 메시지를 보내고 , 액터를 죽인후 다시 뛰워 복구가되는지 살펴봅니다.

Code Block
languagec#
themeEmacs
linenumberstrue
var actorInfo = Props.Create<MySnapShotActor>();
var myactor = actorSystem.ActorOf(actorInfo, "myActor");
for(int i = 0; i < 5; i++)
{
    string message = "t" + i;
    myactor.Tell(message);
}

waitForTest(1000);
myactor.Tell(Akka.Actor.Kill.Instance, ActorRefs.NoSender);
waitForTest(1000);
//액터가 복구되는지 확인합니다.
myactor = actorSystem.ActorOf(actorInfo, "myActor");

...