如何在系统关闭时保存actor的数据

时间:2017-03-15 10:32:31

标签: scala akka

例如,我有以下演员:PlayerGameRoom

GameRoom让玩家得分。当用户离开(终止)时,我们将玩家得分保存在数据库中:

  class Player extends Actor {
        ...
  }


  object GameRoom {
    case object Join
  }

  class GameRoom(database:ActorRef) extends Actor {

    type Score = Int

    var players: Map[ActorRef, Score] = Map.empty

    def receive: Receive = {
      case GameRoom.Join =>
        context.watch(sender())
        players = players + (sender() -> 100)
      case Terminated(player) =>
        players = players - player
        database ! SavePlayerScore(...)
    }

  }

但是如果我想杀死jvm进程(SIGTERM)怎么办?在这种情况下,我无法在关机时将所有用户得分保存到数据库。

任何提示如何实现所需行为?

1 个答案:

答案 0 :(得分:1)

您可以安装一个关闭钩子,在应用程序关闭时终止您的ActorSystem(使用ActorSystem#terminate())。

这将触发Actors层次结构的有序终止,从而导致GameRoom收到Terminated的{​​{1}}。

这是一个安装该关闭钩子的小代码片段:

players

这里需要注意的一件重要事情是:一旦Shutdown Hook中的代码完成,JVM将关闭(即使没有完成也会杀死所有线程),所以如果你有任何其他线程要清理,将其添加到关闭钩子。

编辑1 :即使 Runtime.getRuntime.addShutdownHook( new Thread("shutdown-hook") { override def run() { // This obviously needs to try{ Await.ready(actorSystem.terminate(), Duration(2, TimeUnit.MINUTES)) }catch{ case _ : InterruptedException => // Termination was interrupted case _ : Throwable => // Exception thrown by actor system termination }} })} 抛出异常,JVM也会终止。这意味着,你的某些州可能还没有得到保存或其他什么。您可能希望在那里处理这些异常,因为再次,Await.ready方法完成后,JVM将会死亡。