我试图用PersistentActor实现Saga(进程管理器),它更新多个实体/聚合根以实现(最终)一致性而无需ACID事务。
让我们说,在流程的中间,在Process Manager收到消息并开始处理它之间,jvm崩溃了。
或者正在重新部署应用程序。
在jvm(以及actor系统)重启后,是否会恢复进程管理器的邮箱?
答案 0 :(得分:1)
在JVM崩溃的情况下,邮箱不会被恢复。发送方负责确保其消息被接收/持久化。在持久性参与者之间,使用At-Least-Once Delivery。
答案 1 :(得分:1)
鉴于您已经在使用PersistentActor,因此根据您的需要利用其AtLeastOnceDelivery功能是合理的。 AtLeastOnceDelivery基本上确保持久发送方参与者将继续以可配置的频率向接收方发送消息,直到它收到来自接收方的确认(或从某些终止例程取消正在进行的传送尝试)。
与常规PersistentActor(有或没有AtLeastOnceDelivery)一样,如果JVM崩溃,将重新发送持久性消息。对于AtLeastOnceDelivery,系统恢复时将重新发送持久消息,直到收到确认。 Akka提供方法deliver
来发送标记有连续单调递增deliveryId
的每条消息,并在收到来自接收方的相应deliveryId
的确认后,使用方法confirmDelivery
发出信号成功传递信息。
以下代码段(相关Akka doc的示例代码的一部分)突出显示了发送方actor类(extends PersistentActor with AtLeastOnceDelivery
)中的关键AtLeastOnceDelivery逻辑。请注意,相同的持久性处理程序updateState
用于保留与deliver
和confirmDelivery
对应的事件,以实现一致的状态恢复:
override def receiveCommand: Receive = {
case s: String =>
persist(MsgSent(s))(updateState)
case Confirm(deliveryId) =>
persist(MsgConfirmed(deliveryId))(updateState)
}
override def receiveRecover: Receive = {
case evt: Evt => updateState(evt)
}
def updateState(evt: Evt): Unit = evt match {
case MsgSent(s) =>
deliver(destination)(deliveryId => Msg(deliveryId, s))
case MsgConfirmed(deliveryId) =>
confirmDelivery(deliveryId)
}