actor的默认行为是restart。 为了更好地理解,我创建了两个actor并导致重启:
class PingActor extends Actor with ActorLogging {
import PingActor._
override def postRestart(reason: Throwable): Unit = {
log.info(s"RESTARTING")
super.postRestart(reason)
}
var counter = 0
val pongActor = context.actorOf(PongActor.props, "pongActor")
def receive = {
case Initialize =>
pongActor ! PingMessage("ping")
case PongActor.PongMessage(text) =>
log.info("In PingActor - received message: {}", text)
counter += 1
if (counter == 3) {
log.info("FIN")
context.system.shutdown()
}
if (counter == 2) {
sender() ! PingMessage("ping")
throw new IllegalArgumentException("Aooch")
}
else sender() ! PingMessage("ping")
}
}
object PingActor {
val props = Props[PingActor]
case object Initialize
case class PingMessage(text: String)
}
class PongActor extends Actor with ActorLogging {
import PongActor._
def receive = {
case PingActor.PingMessage(text) =>
log.info("In PongActor - received message: {}", text)
sender() ! PongMessage("pong")
}
}
object PongActor {
val props = Props[PongActor]
case class PongMessage(text: String)
}
所以PingActor
在崩溃之前发送消息,而PongActor
回复当Ping参与者重新启动它时接受消息但发件人(PongActor
)不可用。我确实在deadLetters中看到了这一行
[INFO] [MyActorSystem-akka.actor.default-dispatcher-4] [akka:// MyActorSystem / user / pingActor / pongActor]消息 [com.example.PingActor $ PingMessage]来自 演员[akka:// MyActorSystem / user / pingActor#-1362690296]来 演员[akka:// MyActorSystem / user / pingActor / pongActor#1725419686]是 没送到。 [1]遇到死信。这个日志记录可以 使用配置设置关闭或调整 ' akka.log止字母'和' akka.log-dead-letters-during-shutdown'。
为什么在崩溃之前发送邮件的发件人不可用?有没有办法克服它?
答案 0 :(得分:0)
正如documentation所述,重新启动actor时的默认行为是停止该actor的所有子节点。这就是重启后sender
的消息转到死信的原因。您需要覆盖默认行为并在PongActor
挂钩中设置子项的初始化(即preStart()
)。另外,请移除对super.postRestart(reason)
的调用。
class PingActor extends Actor with ActorLogging {
import PingActor._
override def preStart(): Unit = {
pongActor = Option(context.actorOf(PongActor.props, "pongActor"))
}
override def preRestart(reason: Throwable, message: Option[Any]): Unit = {
log.info("Don't stop the children")
postStop()
}
override def postRestart(reason: Throwable): Unit = {
log.info("RESTARTING")
}
var counter = 0
var pongActor: Option[ActorRef] = None
def receive = {
case Initialize =>
pongActor.foreach(_ ! PingMessage("ping"))
case PongActor.PongMessage(text) =>
...
}
}
进行以上更改会产生以下输出:
In PongActor - received message: ping
In PingActor - received message: pong
In PongActor - received message: ping
In PingActor - received message: pong
In PongActor - received message: ping
Don't stop the children
RESTARTING
In PingActor - received message: pong
In PongActor - received message: ping
In PingActor - received message: pong
In PongActor - received message: ping
Don't stop the children
RESTARTING
In PingActor - received message: pong
In PongActor - received message: ping
In PingActor - received message: pong
In PongActor - received message: ping
Don't stop the children
RESTARTING
In PingActor - received message: pong
In PongActor - received message: ping
...
除了第一个链接之外,还有关于重新启动的更多信息here。