Page History
...
Code Block | ||||
---|---|---|---|---|
| ||||
@Component @Scope("prototype") public class SnapShotActor extends AbstractPersistentActor { private final LoggingAdapter log = Logging.getLogger(getContext().system(), "AbstractPersistentActor"); private Object state; private int snapShotInterval = 5; private int msgCnt = 0; @Override public String persistenceId() { return "ExamplePersistentActor-id-1"; } @Override public Receive createReceiveRecover() { return receiveBuilder(). match(SnapshotOffer.class, s -> { state = s.snapshot(); //상태복원 log.info("상태복원"); // ... }). match(String.class, s -> {/* ...*/}).build(); } // 스냅샷을 지원하는 메시지 정의 @Override public Receive createReceive() { return receiveBuilder(). match(SaveSnapshotSuccess.class, ss -> { SnapshotMetadata metadata = ss.metadata(); // ... }). match(SaveSnapshotFailure.class, sf -> { SnapshotMetadata metadata = sf.metadata(); // ... }). matchEquals("print"match(String.class, scmd -> System.out.println(state) ). //마지막 상태확인{ log.info("EventFired:"+cmd); match if(String.class, cmd ->cmd.indexOf("print") ==0 ) { log.info("EventFired상태확인:"+cmdstate); }else { msgCnt++; if (lastSequenceNr()msgCnt % snapShotInterval == 0 && lastSequenceNr() != 0){ //이벤트가 ?회 발생할때마다,상태를 변경하고 스냅샷을 찍음 ( 테스트를 위한 임의 조건) state = cmd + "을 먹은 상태"; log.info("SaveSnapShot:" + state); saveSnapshot(state); state } = "MyState" + cmd; } saveSnapshot(state); }) .build(); } } |
스냅샷 저장에 필요한 메타정의(SnapshotMetadata) 후 이벤트를 받게되면, 상태가 변경되게되며 자신이 원하는 타이밍에
카메라 셔터(saveSnapshot) 를 누르기만 하면됩니다.
여기서는 수많은 이벤트를 모두 저장하는것은 비효율적이니, 매 5번째 상태의 스냅샷정보를
유지하기로 하였다고 가정하였습니다.
스냅샷 복원
Code Block | ||||
---|---|---|---|---|
| ||||
private Object state; @Override public Receive createReceiveRecover() { return receiveBuilder(). match(SnapshotOffer.class, s -> { state = s.snapshot(); // ... }). match(String.class, s -> {/* ...*/}).build(); } 또는 @Override public Recovery recovery() { return Recovery.create( SnapshotSelectionCriteria .create(457L, System.currentTimeMillis())); } |
...
Code Block | ||||
---|---|---|---|---|
| ||||
protected void persistenceSnapShot() {
new TestKit(system) {{
ActorRef probe = getRef();
Props snapShotActorProp = ext.props("snapShotActor");
System.out.println("snapShotActor 액터생성");
ActorRef snapShotActor = system.actorOf(snapShotActorProp, "snapShotActor");
System.out.println("event 생성");
snapShotActor.tell("커피", ActorRef.noSender());
snapShotActor.tell("사탕", ActorRef.noSender());
snapShotActor.tell("커피", ActorRef.noSender());
snapShotActor.tell("스테이크", ActorRef.noSender());
snapShotActor.tell("라면", ActorRef.noSender()); // <-- 복구기대 상태
snapShotActor.tell("사탕", ActorRef.noSender());
snapShotActor.tell("커피", ActorRef.noSender());
System.out.println("상태확인");
snapShotActor.tell( "print" , ActorRef.noSender());
expectNoMessage(java.time.Duration.ofSeconds(1));
System.out.println("snapShotActor 종료또는 비정상종료");
snapShotActor.tell( akka.actor.PoisonPill.getInstance() , ActorRef.noSender());
expectNoMessage(java.time.Duration.ofSeconds(1));
System.out.println("snapShotActor 마지막 상태 확인");
ActorRef snapShotActo2 = system.actorOf(snapShotActorProp, "eventActor");
System.out.println("상태 복원확인");
snapShotActo2.tell( "print" , ActorRef.noSender());
expectNoMessage(java.time.Duration.ofSeconds(1));
}};
} |
Expand | ||
---|---|---|
| ||
snapShotActor 액터생성 |
샘플은 모든 이용자가 먹을때마다 이벤트가 발생하고,그 시식 결과에의해 어떠한 상태로 변경이 됩니다.
이벤트드리븐 의 예를 간단하게 설명하는것으로 대단한 기능이 있는것은 아닙니다.
단지 이벤트는 무수히 발생하며 모든것을 기록하고 이용하기 어려우니, 스냅샷은 특정한 이벤트 조건에따라(여기서는 단순하게 5번째)
사진을 찍게되며 , 모든 사용자의 청사진을 최근 몇개까지 운영할것인가를 성능과 복원과을 고려하여 설계에 반영할수 있다란것입니다..
스냅샷 시도에따른 반응 메시지
Method | Success | Failure message |
---|---|---|
saveSnapshot(Any) | SaveSnapshotSuccess | SaveSnapshotFailure |
deleteSnapshot(Long) | DeleteSnapshotSuccess | DeleteSnapshotFailure |
deleteSnapshots(SnapshotSelectionCriteria) | DeleteSnapshotsSuccess | DeleteSnapshotsFailure |
스냅샷은 다양한 이유로(디스크풀및 메모리풀등) 실패가 있을수 있으며
그에 대응하는 코드작성도 가능합니다.
다양한 활용 샘플 검색:
원문 참고 :
- https://doc.akka.io/docs/akka/2.5/persistence.html#snapshotsakka persistence snapshot example in google