2016-11-28 34 views
2

我正在開發基於Akka/Play的集羣應用程序,其中前端節點可以被羣集隔離。在這種情況下,我想退出Play應用程序,以便它可以重新啓動並重新加入羣集。調用DefaultApplicationLifecycle.stop時,Play Framework應用程序永不停止

我在各種地方閱讀,優雅地停止播放應用程序的正確方法是使用ApplicationLifecycle。我使用依賴注入來獲取DefaultApplicationLifecycle對象,並在出現ThisActorSystemQuarantinedEvent時調用defaultApplicationLifecycle.stop()

我的問題是,應用程序結束了一個奇怪的狀態,應用程序仍然運行並偵聽HTTP端口,但幾乎沒有任何工作(所有演員似乎都死了)。看來Future從未完成,而我在我的應用程序中沒有定義stopHook。我是否應該在某個時候強制撥打System.exit()

+0

它看起來像所有'DefaultApplicationLifecycle#stop'一樣運行所有的停止鉤子。你需要自己處理實際的過程。如果未來從未完成,很可能是因爲其中一個停止掛鉤由於某種原因未能完成(不是因爲沒有添加),儘管很難說出什麼原因或原因。 –

回答

1

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