Scala / Akka / ReactiveMongo:进程在system.shutdown()之后不会终止

时间:2014-08-06 21:46:35

标签: scala akka actor reactivemongo

我刚开始学习Scala和Akka,现在我正在尝试开发一个使用ReactiveMongo框架连接到MongoDb服务器的应用程序。 问题是,当我在App对象的末尾调用system.shutdown()时,进程不会终止并且会永久挂起。 我现在正在测试没有可用连接的情况,所以我的MongoDB服务器没有运行。我有以下用于查询数据库的actor类:

class MongoDb(val db: String, val nodes: Seq[String], val authentications: Seq[Authenticate] = Seq.empty, val nbChannelsPerNode: Int = 10) extends Actor with ActorLogging {
  def this(config: Config) = this(config.getString("db"), config.getStringList("nodes").asScala.toSeq,
    config.getList("authenticate").asScala.toSeq.map(c => {
      val l = c.unwrapped().asInstanceOf[java.util.HashMap[String, String]]; Authenticate(l.get("db"), l.get("user"), l.get("password"))
    }),
    config.getInt("nbChannelsPerNode"))

  implicit val ec = context.system.dispatcher
  val driver = new MongoDriver(context.system)
  val connection = driver.connection(nodes, authentications, nbChannelsPerNode)
  connection.monitor.ask(WaitForPrimary)(Timeout(30.seconds)).onFailure {
    case reason =>
      log.error("Waiting for MongoDB primary connection timed out: {}", reason)
      log.error("MongoDb actor kills itself as there is no connection available")
      self ! PoisonPill
  }

  val dbConnection = connection(db)
  val tasksCollection = dbConnection("tasks")
  val taskTargetsCollection = dbConnection("taskTargets")

  import Protocol._
  override def receive: Receive = {
    case GetPendingTask =>
      sender ! NoPendingTask
  }
}

我的app类看起来像这样:

object HelloAkkaScala extends App with LazyLogging {
  import scala.concurrent.duration._

  // Create the 'helloakka' actor system
  val system = ActorSystem("helloakka")
  implicit val ec = system.dispatcher

  //val config = ConfigFactory.load(ConfigFactory.load.getString("my.helloakka.app.environment"))
  val config = ConfigFactory.load
  logger.info("Creating MongoDb actor")
  val db = system.actorOf(Props(new MongoDb(config.getConfig("my.helloakka.db.MongoDb"))))

  system.scheduler.scheduleOnce(Duration.create(60, TimeUnit.SECONDS), new Runnable() { def run() = {
    logger.info("Shutting down the system")
    system.shutdown()
    logger.info("System has been shut down!")
  }})
}

我的终端中的日志输出如下所示:

[DEBUG] [08/07/2014 00:32:06.358] [run-main-0] [EventStream(akka://helloakka)] logger log1-Logging$DefaultLogger started
[DEBUG] [08/07/2014 00:32:06.358] [run-main-0] [EventStream(akka://helloakka)] Default Loggers started
00:32:06.443 INFO  [run-main-0] [HelloAkkaScala$] - Creating MongoDb actor
00:32:06.518 DEBUG [helloakka-akka.actor.default-dispatcher-3] [reactivemongo.core.actors.MonitorActor] - Actor[akka://helloakka/temp/$a] is waiting for a primary...  not available, warning as soon a primary is available.
00:32:06.595 DEBUG [helloakka-akka.actor.default-dispatcher-2] [reactivemongo.core.actors.MongoDBSystem] - Channel #-774976050 unavailable (ChannelClosed(-774976050)).
00:32:06.599 DEBUG [helloakka-akka.actor.default-dispatcher-2] [reactivemongo.core.actors.MongoDBSystem] - The entire node set is still unreachable, is there a network problem?
00:32:06.599 DEBUG [helloakka-akka.actor.default-dispatcher-2] [reactivemongo.core.actors.MongoDBSystem] - -774976050 is disconnected
00:32:08.573 DEBUG [helloakka-akka.actor.default-dispatcher-3] [reactivemongo.core.actors.MongoDBSystem] - ConnectAll Job running... Status: Node[localhost: Unknown (0/10 available connections), latency=0], auth=Set()
00:32:08.574 DEBUG [helloakka-akka.actor.default-dispatcher-3] [reactivemongo.core.actors.MongoDBSystem] - Channel #-73322193 unavailable (ChannelClosed(-73322193)).
00:32:08.575 DEBUG [helloakka-akka.actor.default-dispatcher-3] [reactivemongo.core.actors.MongoDBSystem] - The entire node set is still unreachable, is there a network problem?
00:32:08.575 DEBUG [helloakka-akka.actor.default-dispatcher-3] [reactivemongo.core.actors.MongoDBSystem] - -73322193 is disconnected
... (the last 3 messages repeated many times as per documentation the MongoDriver tries to re-connect with 2 seconds interval)
[ERROR] [08/07/2014 00:32:36.474] [helloakka-akka.actor.default-dispatcher-3] [akka://helloakka/user/$a] Waiting for MongoDB primary connection timed out: akka.pattern.AskTimeoutException: Ask timed out on [Actor[akka://helloakka/user/$c#1684233695]] after [30000 ms]
[ERROR] [08/07/2014 00:32:36.475] [helloakka-akka.actor.default-dispatcher-3] [akka://helloakka/user/$a] MongoDb actor kills itself as there is no connection available
... (the same 3 messages repeated again)
00:32:46.461 INFO  [helloakka-akka.actor.default-dispatcher-4] [HelloAkkaScala$] - Shutting down the system
00:32:46.461 INFO  [helloakka-akka.actor.default-dispatcher-4] [HelloAkkaScala$] - Awaiting system termination...
00:32:46.465 WARN  [helloakka-akka.actor.default-dispatcher-2] [reactivemongo.core.actors.MongoDBSystem] - MongoDBSystem Actor[akka://helloakka/user/$b#537715233] stopped.
00:32:46.465 DEBUG [helloakka-akka.actor.default-dispatcher-5] [reactivemongo.core.actors.MonitorActor] - Monitor Actor[akka://helloakka/user/$c#1684233695] stopped.
[DEBUG] [08/07/2014 00:32:46.468] [helloakka-akka.actor.default-dispatcher-2] [EventStream] shutting down: StandardOutLogger started
00:32:46.483 INFO  [helloakka-akka.actor.default-dispatcher-4] [HelloAkkaScala$] - System has been terminated!

之后,这个过程永远持续,永远不会终止。我做错了什么?

1 个答案:

答案 0 :(得分:0)

你做错了什么。这是一个众所周知的问题。

https://github.com/ReactiveMongo/ReactiveMongo/issues/148