2

我正在关注本教程,这是我的代码

case class ArtGroupDeleteFromES (uuidList:List[String]) 
class ArtGroupDeleteESActor extends Actor{
val log = LoggerFactory.getLogger(this.getClass)
    override def preStart() {
      log.debug("preStart  Starting ArtGroupDeleteESActor instance hashcode # {}",
       this.hashCode())
      }

    override def postStop() {
      log.debug("postStop Stopping ArtGroupDeleteESActor instance hashcode # {}",
       this.hashCode())
      }

    override def preRestart(reason: Throwable, message: Option[Any]) {
      log.debug("I am restarting")
      log.debug("ArtGroupDeleteESActor: preRestart")
      log.debug(s" MESSAGE: ${message.getOrElse("")}")
      log.debug(s" REASON: ${reason.getMessage}")
      super.preRestart(reason, message)
      }

    override def postRestart(reason: Throwable) {
      log.debug("restart completed!")
      log.debug("ArtGroupDeleteESActor: postRestart")
      log.debug(s" REASON: ${reason.getMessage}")
      super.postRestart(reason)
      }
def receive = {
  case ArtGroupDeleteFromES(uuidList) =>
 throw new Exception("Booom")
  sender ! true
   }
  case  message => 
    log.warn("Received unknown message: {}", message)
    unhandled(message)
 }

}

这就是我向这个演员发送消息的方式

class ArtGroupDeletionActor extends Actor{

  val log = LoggerFactory.getLogger(this.getClass)
 override val supervisorStrategy = OneForOneStrategy(
                                    maxNrOfRetries = 10, withinTimeRange = 10 seconds) {
    case _:Exception => Restart
  }
 val artGroupDeleteESActor=context.actorOf(Props[ArtGroupDeleteESActor]
      .withDispatcher("akka.actor.ArtGroupDeleteESActor-dispatcher")
      ,name = "ArtGroupDeleteESActor")

   def receive = {

    case DeleteArtGroup(uuidList) =>
      val future1  = ask(artGroupDeleteESActor, ArtGroupDeleteFromES(uuidList)).mapTo[Boolean]
      var isDeletedfromES = Await.result(future1, timeout.duration)
    case message =>
      log.warn("Unhandled message received : {}", message)
      unhandled(message)
  }
}

object test extends App{
 val artGroupDeletionActor=system.actorOf(Props[ArtGroupDeletionActor]
      .withDispatcher("akka.actor.ArtGroupDeletionActor-dispatcher")
      ,name = "ArtGroupDeletionActor")
     artGroupDeletionActor ! DeleteArtGroup(List("123"))
}

PostRestart() 和 preRestart() 方法没有调用,但是 preStart() 和 postStop() 被调用,请指导我哪里做错了

4

1 回答 1

3

(为简单起见,我会打电话给你的演员ParentChild从现在开始)

这里发生的情况是,当内部发生异常时Child.receive,它不会向 发送响应Parent,相反,actor 系统会发送一些用于监督策略的控制指令。但是,在等待 的完成时Parent被阻塞,这仅在超出之后发生,然后依次将 a抛出到内部,杀死(重新启动)actor本身,因此异常的监督消息随后传递给,从不重新启动.Awaitfuture1timeoutTimeoutExceptionParent.receiveParentChilddeadLettersChild

你永远不应该演员内部阻塞,所以这是不正确的:

  val future1 = ask(artGroupDeleteESActor, ArtGroupDeleteFromES(uuidList)).mapTo[Boolean]
  var isDeletedfromES = Await.result(future1, timeout.duration)

相反,您必须在并发环境中使用某种消息标识来区分一个回复和另一个回复,或者将一个添加onComplete到 Future 并self在闭包中发送一条消息(注意:除了发送消息之外,不应在内部执行任何逻辑关闭未来!)。

所以,选项A:

case class ArtGroupDeleteFromES(id: Long, uuidList: List[String])
case class ArtGroupDeleteFromESResult(id: Long, success: Boolean)

class Parent extends Actor {
  override val supervisionStrategy = ...
  var msgId = 0L
  var pendingRequesters = Map.empty[Long, ActorRef]
  val child = context.actorOf(Props[Child])

  def nextId = {
    msgId += 1
    msgId
  }

  def receive = {
    case DeleteArtGroup(uuidList) =>
      val id = nextId
      pendingRequesters += id -> sender() // store a reference to the sender so that you can send it a message when everything completes
      child ! DeleteArtGroupFromES(nextId, uuidList)
    case ArtGroupDeleteFromESResult(id, success) =>
      // process result...
      pendingRequesters(id) ! "done"
      pendingRequesters -= id
  }
}

和选项 B:

case class ArtGroupDeleteFromES(uuidList: List[String])
case class ArtGroupDeleteFromESResult(replyTo: ActorRef, success: Boolean)

class Parent extends Actor {
  override val supervisionStrategy = ...
  val child = context.actorOf(Props[Child])

  def receive = {
    case DeleteArtGroup(uuidList) =>
      val requester = sender() // when the future completes, sender may have already changed, so you need to remember it
      (child ? DeleteArtGroupFromES(uuidList)).onComplete {
        case Success(success) => self ! ArtGroupDeleteFromESResult(requester, success)
        case Failure(e) =>
          log.warn("Could not delete...", e) 
          self ! ArtGroupDeleteFromESResult(requester, success = false)
  }
}
于 2016-06-03T08:29:30.407 回答