我有一些消息传递应用程序需要至少一次保证。 正如我从文档中所理解的那样:akka-persistence - 是关于演员状态的。它使用一些逐层的意识形态来处理这种状态。
在文档中我发现了一些AbstractPersistentActorWithAtLeastOnceDelivery,它似乎在提出这种保证。但是现在我对这个概念有一些疑问:
我的演员是一个简单的发射器,我所需要的只是交付保证。所以我实际上并不关心演员状态以及消耗宝贵记忆的所有分层。广泛的期刊能成为问题的原因吗?
演员:
public class SafeSenderActor extends AbstractPersistentActorWithAtLeastOnceDelivery {
private String persistenceId;
private ActorSelection destination;
public SafeSenderActor() {
System.out.println("SafeSenderActor created");
this.persistenceId = "safe-persistent-actor-id-" + UUID.randomUUID();
destination = context().actorSelection("/user/safeReceiverRouter");
}
@Override
public String persistenceId() {
return persistenceId;
}
@Override
public AbstractActor.Receive createReceive() {
return ReceiveBuilder.create()
.match(SenderTaskMessage.class, msg -> {
persistAsync(new MsgSentEvent(msg.getTestMessage()), this::updateState);
})
.match(ConfirmRobustMessageDelivery.class, ack -> {
persistAsync(new MsgConfirmEvent(ack.getMessageId(), ack.getLocalMessageNumber()), this::updateState);
})
.build();
}
@Override
public Receive createReceiveRecover() {
return receiveBuilder().match(Object.class, this::updateState).build();
}
private void updateState(Object event) {
if (event instanceof MsgSentEvent) {
MsgSentEvent ev = (MsgSentEvent) event;
deliver(destination, deliveryId -> new RobustTestMessage(deliveryId, ev.getMessage()));
} else if (event instanceof MsgConfirmEvent) {
MsgConfirmEvent ev = (MsgConfirmEvent) event;
confirmDelivery(ev.getDeliveryId());
}
}
}
经过一段连续的消息传递后,我收到错误:
[ERROR] [07/06/2017 01:40:33.446] [sender-system-akka.actor.default-dispatcher-50] [akka://sender-system@127.0.0.1:6666/user/safeSendersRouter/$d] Failed to persist event type [com.test.common.events.MsgSentEvent] with sequence number [358698] for persistenceId [safe-persistent-actor-id-648ec66d-7b7f-4291-b3a2-9bd395d92dc7]. (akka.pattern.CircuitBreaker$$anon$1: Circuit Breaker Timed out.)
我正在使用leveldb作为期刊。
答案 0 :(得分:0)
可能要花很长时间,但回答它仍然很有用。您可以覆盖方法onPersistFailure
和onPersistRejected
来调查您提到的错误。如果持久化失败,将调用onPersistFailure
方法。演员会弯腰。最好的做法是过一会儿再启动演员,并使用Backoff主管。如果JOURNAl无法持久化事件,则调用onPersistRejected
方法。演员恢复了。
public class SafeSenderActor extends AbstractPersistentActorWithAtLeastOnceDelivery implements ActorLogging {
...
...
...
@Override
public void onPersistFailure(Throwable cause, Object event, long seqNr) {
log().error("fail to persist $event because of: {}", cause);
super.onPersistFailure(cause, event, seqNr);
}
@Override
public void onPersistRejected(Throwable cause, Object event, long seqNr) {
log().error("persist rejected for {} because of: {}", event, cause);
super.onPersistRejected(cause, event, seqNr);
}
}