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

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

问题描述:

我正在开发基于Akka/Play的集群应用程序,其中前端节点可以被群集隔离。在这种情况下,我想退出Play应用程序,以便它可以重新启动并重新加入群集。调用DefaultApplicationLifecycle.stop时,Play Framework应用程序永不停止

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

我的问题是,应用程序结束了一个奇怪的状态,应用程序仍然运行并侦听HTTP端口,但几乎没有任何工作(所有演员似乎都死了)。看来Future从未完成,而我在我的应用程序中没有定义stopHook。我是否应该在某个时候强制拨打System.exit()

+0

它看起来像所有'DefaultApplicationLifecycle#stop'一样运行所有的停止钩子。你需要自己处理实际的过程。如果未来从未完成,很可能是因为其中一个停止挂钩由于某种原因未能完成(不是因为没有添加),尽管很难说出什么原因或原因。 –

ApplicationLifecycle用于注册应用程序停止时执行的挂钩。不过,它不应该被用来停止应用程序。从docs

这是用来挂钩到Play生命周期事件,特别是当播放停止时。当应用程序被关闭,在倒车时,从它们注册

...

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

你真正想要的是一个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() 
    } 
} 
+0

谢谢!我只是想知道为什么我的defaultApplication生命周期的未来从未被称为:S。我会尝试你的建议,谢谢! – CanardMoussant

+0

其实我看到完全相同的行为:应用程序停留在陈旧状态。我想知道如何调试应用程序永不停止的事实。 – CanardMoussant

+0

我想念你的问题的细节。查看关于如何停止服务器的编辑。 – marcospereira