克服Akka Persistence中对持久性消息类的更改

时间:2014-08-19 09:39:48

标签: scala akka akka-persistence

让我们说我开始使用像这样的Akka Persistence系统:

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的实例尝试恢复其状态时,日志消息将属于前一个案例类。因为它期望后一种类型,它将抛出OnReplayFailure,使处理器无用。问题是:如果我们假设缺席y可以等于0(或者其他什么),那么最好的做法是克服这个问题吗?例如,在恢复时可能使用implicit从前一条消息转换为后一条消息?

1 个答案:

答案 0 :(得分:1)

Akka默认使用Java序列化,并表示对于长期项目,我们应该使用适当的替代方案。这是因为Java序列化很难随着时间的推移而发展。 Akka建议使用Google Protocol Buffers,Apache Thrift或Apache Avro。

例如,对于Google协议缓冲区,在您的情况下,您将编写如下内容:

if (p.hasY) p.getY else 0

Akka在一篇很好的文章中解释了所有这些(不可否​​认,它不具备谷歌能力):

http://doc.akka.io/docs/akka/current/scala/persistence-schema-evolution.html

甚至解释了为现有消息类型添加新字段的特定用例:

http://doc.akka.io/docs/akka/current/scala/persistence-schema-evolution.html#Add_fields

Akka文档推荐用于比较不同序列化工具包的博客文章:

http://martin.kleppmann.com/2012/12/05/schema-evolution-in-avro-protocol-buffers-thrift.html