【问题标题】:Akka - resending the "breaking" messageAkka - 重新发送“破坏”消息
【发布时间】: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


【解决方案1】:

您已经在 preRestart 中收到失败消息(请参阅:消息:Option[Any]),因此无需自己隐藏它。是的,将它重新发送给自己是完全可以的,但要小心无限重启与此结合,因为您很可能最终会收到一条永远不会被丢弃的消息。

【讨论】:

  • 只要您设置了 MaxNrOfRetries,您就不应该无限重启,对吧?
  • 可以在preStart中转发邮件以保留原始发件人吗?
  • @jpierson 是的,你可以,因为sender 保留在演员的context 中。 (我也有同样的问题)
猜你喜欢
  • 1970-01-01
  • 2013-04-30
  • 2012-10-09
  • 2023-03-17
  • 2014-05-11
  • 2016-09-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多