我尝试使用Akka(版本2.4.0)Persistency和Cassandra Plugin(版本0.6,https://github.com/krasserm/akka-persistence-cassandra)编写应用程序以从故障中恢复。
事件被存储到cassandra没有问题,但是,我试图杀死和演员,所以主管重新启动它,receiveRecover
没有收到事件。
似乎问题在于插件本身,就好像我使用共享的LevelDB而不是cassandra一样,事件正在恢复步骤中接收。
这是我的持久性演员的实现:
class SimplePersistentActor extends PersistentActor with ActorLogging {
def persistenceId: String = context.self.path.name
override def preRestart(cause: Throwable, msg: Option[Any]) = {
log.debug(s"Restarting ${getClass.getSimpleName}")
super.preRestart(cause, msg)
}
override def postStop() = {
log.debug(s"Stopping ${getClass.getSimpleName}")
super.postStop()
}
var transactionData: Either[UninitializedData, RunningTransactionData] = Left(UninitializedData())
def receiveCommand ={
case msg @ TransactionStart(transactionId) =>
persist(msg) { _ => }
log.debug(s"Starting a transaction with id $transactionId")
transactionData = Right(RunningTransactionData(transactionId, List()))
/* Send a reply */
sender() ! transactionId
case msg @ TransactionData(data) =>
persist(msg) { _ => }
transactionData match {
case Right(t: RunningTransactionData) =>
val updatedTransaction = t.copy(data = t.data ::: List(data))
log.debug(s"There are ${updatedTransaction.data.size} data items within a transaction ${t.transactionId}")
transactionData = Right(updatedTransaction)
/* Send a reply */
sender() ! t.transactionId
case _ => log.error("Actor's transaction data is not initialized")
}
case TransactionEnd(transactionId) =>
transactionData match {
case Right(t: RunningTransactionData) =>
log.debug(s"Ending a transaction with id ${t.transactionId}")
transactionData = Left(UninitializedData())
/* Send a reply */
sender() ! t.transactionId
case _ => log.error("Actor's transaction data is not initialized")
}
case other =>
log.debug(s"Unexpected event received: $other")
}
def receiveRecover = {
case message =>
log.debug(s"Recovery Step. Message $message received")
}
}
在上面描述的两种情况下,代码都没有改变。 有没有人见过这个问题?
答案 0 :(得分:0)
我遇到了同样的事情,并找到了适合我的修复程序。我知道您的问题已经很老了,但是由于我在最新版本的Akka Cassandra Persistence(0.86)上看到了同样的问题,因此我认为值得一提。
我遇到的问题来自以下配置。
cassandra-main-journal = ${cassandra-journal} {
contact-points = ["localhost"]
keyspace-autocreate = true
tables-autocreate = true
keyspace = "main_akka_journal"
}
因此,采用默认的cassandra-journal
配置并覆盖keyspace
。然后,就像您在做的那样,在Akka持久性actor中覆盖persistenceId
以指向此配置。
如果执行此操作,将所有对Actor的写入都转到main_akka_journal
键空间。重新启动Actor时,您会收到一条RecoveryCompleted
消息,但是看不到您编写的任何消息。但是,当您收到RecoveryCompleted
时,lastSequenceNr
将是正确的。
有趣的是,如果您拥有keyspace-autocreate=true
,则会在创建的地方看到两个键空间。 main_akka_journal
和akka
。
所以问题是持久性参与者正在写入main_akka_journal
密钥空间,重新启动时它是从akka
密钥空间(为空)中读取事件,然后从lastSequenceNr
中读取事件。 main_akka_journal
键空间(正确)。
对我来说,解决方案是此配置:
cassandra-main-journal = ${cassandra-journal} {
contact-points = ["localhost"]
keyspace-autocreate = true
tables-autocreate = true
keyspace = "main_akka_journal"
query-plugin = "cassandra-main-query-plugin"
}
cassandra-main-query-plugin = ${cassandra-query-journal} {
write-plugin = "cassandra-main-journal"
}
否则默认情况下,write-plugin
指向cassandra-journal
和akka
键空间。