【问题标题】:Akka Scala actor scheduled message does not appear to fireAkka Scala 演员计划的消息似乎没有触发
【发布时间】:2014-04-08 14:32:54
【问题描述】:

在对 Akka 演员进行试验时,我设计了一个与预期不太相符的用例。我定义了一个演员,MyActor,它接收"start" 消息。此消息启动一个调度程序,该调度程序应将消息"request" 转发给它self1 second。代码如下:

import akka.actor._
import scala.concurrent.Await
import scala.concurrent.duration._
import akka.pattern.gracefulStop
import scala.concurrent.ExecutionContext.Implicits.global

object ScheduledActors {

  def main(args: Array[String]) {

    implicit val system = ActorSystem("ScheduledActors")
    val admin = system.actorOf(Props[MyActor], name = "my-actor")

    admin ! "start"

    val adminFuture = gracefulStop(admin, 2 minutes)
    Await.result(adminFuture, 2 minutes)
  }

class MyActor extends Actor {

  var cancellableOption: Option[Cancellable] = None

  def receive = {

    case "start" =>
      println("start")

      cancellableOption =
        Some(context.system.scheduler.schedule(0 seconds, 1 second) { self ! "request" })

    case "request" =>
      println("request")

    case "stop" =>
      println("stop")

      cancellableOption match {
        case None => // no-op
        case Some(v) => v.cancel()
      }

      context.stop(self)
    }
  }
}

我尝试了几种变体。利用带有显式ActorRefmessageschedule 方法变体。例如:

schedule(initialDelay: Duration, frequency: Duration, receiver: ActorRef, message: Any): Cancellable

在每种情况下,"request" 消息似乎从未被参与者收到。该块肯定被称为,因为我已经使用println 语句作为健全性检查进行了验证。但是送货是不行的。

这让我想到self 引用在此上下文中实际执行时可能不会提供相同的上下文(à la ForkJoinPool 调用)。 Akka 文档确实警告不要在调度调用的上下文中使用不稳定的引用。然而,self 作为接收者被明确引用为reasonable alternative

在这一点上,我有点不知所措。任何帮助是极大的赞赏。

【问题讨论】:

    标签: scala akka


    【解决方案1】:

    这是因为演员已经被终止了。运行时,您应该会看到已记录的死信,例如:

    [INFO] [04/08/2014 17:05:03.903] [ScheduledActors-akka.actor.default-dispatcher-2] [akka://ScheduledActors/user/my-actor] 消息 [java.lang.从 Actor[akka://ScheduledActors/user/my-actor#-1824493491] 到 Actor[akka://ScheduledActors/user/my-actor#-1824493491] 的字符串] 未交付。 [1] 遇到死信。可以使用配置设置“akka.log-dead-letters”和“akka.log-dead-letters-during-shutdown”关闭或调整此日志记录。

    GracefulStop 不知道您已完成的调度并停止 actor,因为邮箱是空的。 如果您将 main 方法更改为以下内容,您应该会看到以下消息:

    implicit val system = ActorSystem("ScheduledActors")
    val admin = system.actorOf(Props[MyActor], name = "my-actor")
    
    admin ! "start"
    
    Thread.sleep(5000)
    admin ! "stop"
    

    【讨论】:

    • 你说得对。我花了太多时间过度分析调度程序,并且没有认识到gracefulStop 只是在其他消息被转发之前完成了它的工作。感谢您的回复!
    猜你喜欢
    • 2012-10-09
    • 2015-03-28
    • 1970-01-01
    • 2018-09-29
    • 2014-12-02
    • 2019-04-23
    • 1970-01-01
    • 2021-01-11
    • 2013-11-29
    相关资源
    最近更新 更多