调用DefaultApplicationLifecycle.stop时,Play Framework应用程序永远不会停止

时间:2016-11-28 15:07:50

标签: scala playframework akka

我正在开发一个基于Akka / Play的集群应用程序,其中前端节点可以被集群隔离。在这种情况下,我想退出Play应用程序,以便可以重新启动它并重新加入群集。

我在各个地方读到,优雅地停止播放应用程序的正确方法是使用ApplicationLifecycle。我使用依赖注入来获取DefaultApplicationLifecycle对象,并在defaultApplicationLifecycle.stop()发生时调用ThisActorSystemQuarantinedEvent

我的问题是应用程序最终处于一个奇怪的状态,应用程序仍在运行并侦听HTTP端口,但几乎没有任何工作(所有演员似乎都死了)。在我的应用程序中没有定义Future时,stopHook似乎永远不会完成。我应该强行在某个时候致电System.exit()吗?

1 个答案:

答案 0 :(得分:2)

ApplicationLifecycle用于注册应用程序停止时执行的挂钩。但它不应该用于停止应用程序。来自docs

  

这用于挂钩播放生命周期事件,特别是播放停止时。

     

...

     

应用程序关闭时执行停止挂钩,与注册时相反。由于这种反向排序,只要组件没有收到关闭事件,组件就可以知道使用它所依赖的组件是安全的。

您真正想要的是Application实例。来自Application.stop docs

  

停止申请。当所有停止钩子都已运行时,返回的未来将被兑换。

当调用Application.stop时,ApplicationLifecycle中的所有挂钩寄存器都在“从注册时起反向”执行。您也可以使用依赖注入获取Application实例:

class SomeClass @Inject() (app: Application) {
    def somethingHappensThatRequireApplicationToStop() = app.stop()
}

您仍然可以接收请求,因为您刚停止了应用程序,而不是Server。不完全确定它,但我认为你可以像注入上面的应用程序一样注入它:

import play.core.server.Server

class SomeClass @Inject() (app: Application, server: Server) {
    def somethingHappensThatRequireApplicationToStop() = {
        app.stop()
        server.stop()
    }   
}

此外,由于它停止服务器会强制停止应用,您只需要以下内容:

import play.core.server.Server

class SomeClass @Inject() (server: Server) {
    def somethingHappensThatRequireToStop() = {
        server.stop()
    }   
}