Scala 克服Akka持久化中持久消息类的变化
假设我从一个Akka持久性系统开始,如下所示:Scala 克服Akka持久化中持久消息类的变化,scala,akka,akka-persistence,Scala,Akka,Akka Persistence,假设我从一个Akka持久性系统开始,如下所示: case class MyMessage(x: Int) class MyProcessor extends Processor { def receive = { case Persistent(m @ MyMessage) => m.x //... } } 然后有一天我把它改成这样: case class MyMessage(x: Int, y: Int) class MyProcessor extends
case class MyMessage(x: Int)
class MyProcessor extends Processor {
def receive = {
case Persistent(m @ MyMessage) => m.x
//...
}
}
然后有一天我把它改成这样:
case class MyMessage(x: Int, y: Int)
class MyProcessor extends Processor {
def receive = {
case Persistent(m @ MyMessage) => m.x + m.y
//...
}
}
部署新系统后,当
MyProcessor
的实例尝试恢复其状态时,日志消息将属于前一个case类。因为它需要后一种类型,所以它将抛出一个OnReplayFailureOnReplayFailure
,使处理器无用。问题是:如果我们假设一个缺席的y
可以等于0
(或其他什么),那么有没有克服这个问题的最佳实践?例如,可能在恢复时使用隐式
将前一条消息转换为后一条消息?Akka默认使用Java序列化,并表示对于长期项目,我们应该使用适当的替代方法。这是因为Java序列化很难随着时间的推移而发展。Akka建议使用Google协议缓冲区、Apache Thrift或Apache Avro
例如,使用Google协议缓冲区,您可以编写如下内容:
if (p.hasY) p.getY else 0
Akka在一篇很好的文章中解释了这一切(无可否认,它不太适合谷歌搜索):
甚至解释了向现有消息类型添加新字段的特定用例:
Akka文档中的一篇博客文章建议对不同的序列化工具包进行比较:
如果没有消息丢失很重要,我会在切换后保留旧消息格式以实现向后兼容性(可能是另一个名称)一段时间(以便您可以将剩余的旧消息与新消息一起处理)。@Ashalynd在我的情况下,理论上,客户机可以在旧处理器失效数年后重新启动。保留旧代码以实现向后兼容性可能会变得非常臃肿。但如果没有其他办法,那就是解决办法了。这让事情变得很糟糕,但奥托,也许几年后这些信息就不再相关了。您还可以定义一个“全面”匹配器以实现向后兼容性。