Akka.Net内存持久化场景下应用重启后Recover方法异常触发问题咨询
问题解答
问题1:内存存储为什么会收到SnapshotOffer
Akka.Persistence的内置内存持久化插件设计初衷就是模拟真实持久化存储的完整行为,它存储的快照、事件数据是保存在ActorSystem级别的全局内存缓存中,和单个Actor实例的生命周期无关。
只要ActorSystem没有销毁,你调用SaveSnapshot存储的快照会一直被内存插件留存,当你Stop旧Actor实例、重建相同PersistenceId的Actor实例时,持久化模块会正常从内存插件中读取之前保存的快照,给新Actor实例发送SnapshotOffer触发恢复流程,这个是符合设计预期的正常行为。
问题2:使用Guid生成新PersistenceId问题依然存在的常见原因
- 首先排查代码拼写问题:你代码中字段名用的是
_persistanceId(拼写错误,正确应为persistence),如果你的Guid生成逻辑赋值的变量和PersistenceId属性返回的字段不是同一个,就会出现生成的新ID没有实际生效的问题。 - 其次排查测试逻辑问题:如果你的Guid是定义为静态变量、或者在测试用例外提前生成,每次跑用例拿到的还是同一个ID,自然不会生效。
- 额外注意:你当前贴出的测试代码中
persistenceId是写死的固定字符串,和你描述的用Guid生成的逻辑不符,请确认实际运行的测试代码是否正确替换了ID。
你观察到的异常行为根因
你遇到的「Actor重建后没发新消息就触发OnPrediction」本质是恢复逻辑编写错误:
你在OnRecover拿到快照后,遍历所有历史请求调用OnPrediction,而OnPrediction里会执行业务逻辑(给Sender发ok消息)+ 再次保存快照。等于Actor恢复阶段就会把所有历史请求重新处理一遍,自然会出现你没有主动发消息也能收到回复的现象。
正确的恢复逻辑应该是直接把快照赋值给当前_state变量,不要重复调用业务处理方法:
private void OnRecover(PredictionManagerState state) { // 直接赋值状态即可,不需要重新执行业务逻辑 _state = state; }
内容的提问来源于stack exchange,提问作者lobstar
相关产品推荐
相关产品推荐

