Page History
Info |
---|
At-Least-Once Delivery - 적어도 메시지를 한번 보내려는 메카니즘으로 PersistenceActor와 결합하여 실패없는 메시지 전송 목표를 달성할수 있습니다. 적어도 한번 보내려는 메카니즘으로 인해 중복 메시지 발생할수 있음에 유의하여 작성 해보겠습니다. |
이것은 전송한 메시지가 수신처에 도달되는 것을 보장되기를 원할때 유용합니다.
아주 착한 택배 서비스 시나리오를 가정해봅시다.
택배 아저씨는 택배를 대상에게 일반적으로 아주 빠르게 대부분 성공을 하며, 물건 분실을
방지하고자 꼭 수신받았음을 확인을 합니다. 하지만 받을사람이 부재중이라고 가정해봅시다.
택배 아저씨는 자신이 해야할 일을 하는동시에, 부재중을 체크하면서 다른 고객의 물건도 보내려고 할것입니다.
결국 자신이 배달해야할 모든 택배를 모두 보내게 되며, 물건은 복제가 안되기때문에 중복없이 꼭 한번만 보내게 됩니다.
상대편이 편지를 수신을 받았나? 일반 우편과는 다른 메시지처리방식입니다.
메시지와 확인된 메시지 정의하기
Code Block | ||||
---|---|---|---|---|
| ||||
class Msg implements Serializable { private static final long serialVersionUID = 1L; public final long deliveryId; public final String s; public Msg(long deliveryId, String s) { this.deliveryId = deliveryId; this.s = s; } } class Confirm implements Serializable { private static final long serialVersionUID = 1L; public final long deliveryId; public Confirm(long deliveryId) { this.deliveryId = deliveryId; } } class MsgSent implements Serializable { private static final long serialVersionUID = 1L; public final String s; public MsgSent(String s) { this.s = s; } } class MsgConfirmed implements Serializable { private static final long serialVersionUID = 1L; public final long deliveryId; public MsgConfirmed(long deliveryId) { this.deliveryId = deliveryId; } } |
메시지는 전송시 유니크한 배달ID가 발생하며, 최송 수신처 에게 확인을통해
실패한 메시지에대해 재전송을 할수가 있습니다. 이러한 과정없이 네트워크 에러를 감지하여
실패시 재전송을 하려는 전략은 실패할 가능성이 높습니다.
어디서 유실되었는지 파악하는것이 더 어렵기 때문입니다.
AtLeastOnceDelivery 액터 설계
송신자 설계
Code Block | ||||
---|---|---|---|---|
| ||||
class MyPersistentActor extends AbstractPersistentActorWithAtLeastOnceDelivery { private final ActorSelection destination; public MyPersistentActor(ActorSelection destination) { this.destination = destination; } @Override public String persistenceId() { return "persistence-id"; } @Override public Receive createReceive() { return receiveBuilder(). match(String.class, s -> { persist(new MsgSent(s), evt -> updateState(evt)); }). match(Confirm.class, confirm -> { persist(new MsgConfirmed(confirm.deliveryId), evt -> updateState(evt)); }). build(); } @Override public Receive createReceiveRecover() { return receiveBuilder(). match(Object.class, evt -> updateState(evt)).build(); } void updateState(Object event) { if (event instanceof MsgSent) { final MsgSent evt = (MsgSent) event; deliver(destination, deliveryId -> new Msg(deliveryId, evt.s)); } else if (event instanceof MsgConfirmed) { final MsgConfirmed evt = (MsgConfirmed) event; confirmDelivery(evt.deliveryId); } } } |
수신자 설계
Code Block | ||||
---|---|---|---|---|
| ||||
class MyDestination extends AbstractActor { @Override public Receive createReceive() { return receiveBuilder() .match(Msg.class, msg -> { // ... getSender().tell(new Confirm(msg.deliveryId), getSelf()); }) .build(); } } |