Page History
Info |
---|
At-Least-Once Delivery - 적어도 메시지를 한번 보내려는 메카니즘으로 PersistenceActor와 결합하여 목표를 달성할수 있습니다. 보낼려는 메시지가 유실될수 있는 가능성을 제거하며 적어도 한번보내려는 메카니즘으로 인해 중복 메시지 발생에 유의하여 작성 해보겠습니다.해보겠습니다. |
이것은 메시지를 무조건 한번만 보내야할때 유용합니다. 아주 착한 택배 서비스 시나리오를 가정해봅시다.
택배 아저씨는 택배를 대상에게 일반적으로 아주 빠르게 대부분 성공을 하며, 물건 분실을
방지하고자 꼭 수신인 실명을 확인을 합니다. 하지만 받을사람이 부재중이라고 가정해봅시다.
택배 아저씨는 자신이 해야할 일을 하는동시에, 부재중을 체크하면서 보내려고 할것입니다.
결국 자신이 배달해야할 모든 택배를 모두 보내게 되며, 물건은 복제가 안되기때문에 중복없이
꼭 한번만 보내게 됩니다. 상대편이 선물을 받았나? 안받았나?
확인안하는 산타클로스 할아버지와는 다른 메카니즘입니다.
메시지설계
Code Block | ||||
---|---|---|---|---|
| ||||
public class Msg
{
public Msg(long deliveryId, string message)
{
DeliveryId = deliveryId;
Message = message;
}
public long DeliveryId { get; }
public string Message { get; }
}
public class Confirm
{
public Confirm(long deliveryId)
{
DeliveryId = deliveryId;
}
public long DeliveryId { get; }
}
public interface IEvent
{
}
public class MsgSent : IEvent
{
public MsgSent(string message)
{
Message = message;
}
public string Message { get; }
}
public class MsgConfirmed : IEvent
{
public MsgConfirmed(long deliveryId)
{
DeliveryId = deliveryId;
}
public long DeliveryId { get; }
}
|
액터설계
Code Block | ||||
---|---|---|---|---|
| ||||
public class ExampleDestinationAtLeastOnceDeliveryReceiveActor : ReceiveActor
{
private ILoggingAdapter log = Context.GetLogger();
protected int messageCnt = 0;
public ExampleDestinationAtLeastOnceDeliveryReceiveActor()
{
Receive<Msg>(msg =>
{
messageCnt++;
//Test를 위해 메시지를 못받은척한다.
if (messageCnt % 2 ==0)
{
log.Warning("Test for Drop Message");
return;
}
log.Debug("Yes I can");
Sender.Tell(new Confirm(msg.DeliveryId), Self);
});
}
}
public class ExampleAtLeastOnceDeliveryReceiveActor : AtLeastOnceDeliveryReceiveActor
{
private readonly IActorRef _destionationActor = Context.ActorOf<ExampleDestinationAtLeastOnceDeliveryReceiveActor>();
private ILoggingAdapter log = Context.GetLogger();
public ExampleAtLeastOnceDeliveryReceiveActor()
{
Recover<MsgSent>(msgSent => Handler(msgSent));
Recover<MsgConfirmed>(msgConfirmed => Handler(msgConfirmed));
Command<string>(str =>
{
log.Debug("received:" + str);
Persist(new MsgSent(str), Handler);
});
Command<Confirm>(confirm =>
{
//메시지 받음을 확인하고, 해당 메시지를 더이상 안보낸다.
log.Debug("received confirm:" + confirm.DeliveryId);
Persist(new MsgConfirmed(confirm.DeliveryId), Handler);
});
}
private void Handler(MsgSent msgSent)
{
Deliver(_destionationActor.Path, l => new Msg(l, msgSent.Message));
}
private void Handler(MsgConfirmed msgConfirmed)
{
ConfirmDelivery(msgConfirmed.DeliveryId);
}
public override string PersistenceId { get; } = "persistence-id";
} |
TestCode
테스트 케이스
- 메시지 10개를 한꺼번에 보낸다.
- 받는 쪽에서 짝수번째 메시지를 못본채한다.( test 시나리오)
- 우선 홀수 메시지는 모두 전송됨을 확인
- 메시지 전송에 실패가난 짝수번째 메시지도 다시전송하여 결국 성공시킨다.(홀수번쨰 성공)
Code Block | ||||
---|---|---|---|---|
| ||||
var actorInfo = Props.Create<ExampleAtLeastOnceDeliveryReceiveActor>();
var myactor = actorSystem.ActorOf(actorInfo, "myActor");
for(int i=0;i<10;i++)
myactor.Tell("can you speak english?"); |
Expand | ||
---|---|---|
| ||