【发布时间】:2012-11-12 15:15:05
【问题描述】:
在官方akka 2.0.4 docs 中写道:
actor 重启只替换实际的actor对象;邮箱内容不受重启影响, 因此消息的处理将在 postRestart 钩子返回后恢复。触发的消息 不会再次收到异常。重新启动时发送给actor的任何消息都将排队到它的队列中 邮箱照常。
假设我有一条消息导致我的演员重新启动。它不再在邮箱中,因此将不会被取代它的演员处理。如果我希望无论如何都由演员处理此消息(假设在这种情况下顺序无关紧要),那么演员在重新启动时将消息发送给自己会是一个坏主意吗?
一些(伪)代码来说明我的意思:
class ResendingActor extends Actor {
var curMessage: Option[MyMessage] = None
def receive = {
case MyMessage(x) => {
curMessage = Some(MyMessage(x))
/* processing */
curMessage = None
}
}
override def preRestart(reason: Throwable, message: Option[Any]) {
curMessage match {
case Some(x) => self ! x
case None => ;
}
}
}
这样,在重新启动之前未由参与者处理的消息将被推送到新参与者的队列末尾。
所以我的问题是:我有什么理由不应该这样做吗?
我唯一能想到的是,如果消息由于某种原因格式错误,它永远不会离开系统并导致actor定期重启......
【问题讨论】:
-
您的最后一个假设是正确的,一遍又一遍地重新传递相同的消息是问题之一,称为poison message。
-
假设您的错误处理足够完整,以至于任何此类消息都是意外的(而不是已知的边缘情况),我认为更好的解决方案是记录消息以便可以手动检查,而不是尝试重新处理它。否则,您应该能够在不使参与者崩溃的情况下处理消息。
标签: scala playframework akka