我正在开发一个基于Akka / Play的集群应用程序,其中前端节点可以被集群隔离。在这种情况下,我想退出Play应用程序,以便可以重新启动它并重新加入群集。
我在各个地方读到,优雅地停止播放应用程序的正确方法是使用ApplicationLifecycle
。我使用依赖注入来获取DefaultApplicationLifecycle
对象,并在defaultApplicationLifecycle.stop()
发生时调用ThisActorSystemQuarantinedEvent
。
我的问题是应用程序最终处于一个奇怪的状态,应用程序仍在运行并侦听HTTP端口,但几乎没有任何工作(所有演员似乎都死了)。在我的应用程序中没有定义Future
时,stopHook
似乎永远不会完成。我应该强行在某个时候致电System.exit()
吗?
答案 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()
}
}