2016-04-22 42 views
0

我寫過一些actor類,我發現我必須處理這些實體的生命週期。例如,當我的actor初始化時,我想調用一個方法,這樣我就可以在消息隊列中設置一些偵聽器(或打開數據庫連接等)。Akka相當於Spring InitializingBean

這是否與此相當?相當於我能想到的是Spring的InitialisingBean和DisposableBean

+0

我看到像啓動前()等方法,但我似乎並沒有得到回調這些方法。 –

回答

1

這是一個典型的場景,你會喜歡override methodspreStart()postStop(),等我看不出什麼錯。

當然,您必須瞭解詳細信息 - 例如postStop()在調用actor.stop()後異步調用,而preStart()在調用Actor時調用。這意味着可能會緩慢/阻止諸如數據庫交互的操作應儘量少。

您還可以使用Actor的構造函數來初始化數據。

正如馬修所說,監督在阿卡中扮演着重要角色 - 所以你可以指導主管在事件上執行特定的事情。例如,所謂的DeathWatch - 你可以當演員「您正在觀看在」一模通知:

context.watch(child) 

... 

def receive = { 
    case Terminated(`child`) => lastSender ! "finished" 
} 
+0

由於其生命週期(它比清理資源的最終化方法更可靠),postStop可能是一個有價值的回調函數。 preStart,在實例化之後被actor系統直接調用,具有與構造函數基本相同的生命週期。 –

+1

是的,但還有一點。在'postRestart'的默認實現中''preStart'被調用 - 所以也可以覆蓋'postRestart',然後跳過第二次調用'preStart'或者在某些情況下調用它。但這真是一個極端的例子。 – Anton

+0

我希望看到改進的設計:)。但那很酷 –

1

一個Actor基本上是兩個方法 - 一個構造函數和onMessage(Object): void

它的生命週期中沒有任何東西自然地提供了「佈線」行爲,這爲您留下了幾個選擇。

  1. 使用監事演員來創建其他演員。監督員負責監視,啓動和重新啓動參與者失敗 - 因此,讓監督人員瞭解集成系統的狀態以避免持續重新啓動通常很有價值。該主管將創建和管理服務對象(可能通過Spring)並將它們傳遞給Actor。

  2. 在Actor構建時使用您的首選初始化技術。這是棘手的,但你可以肯定結合春天與演員。要知道,如果一個主管重新啓動你的角色,你需要能夠從你放置在Props對象中的任何內容中恢復它所需的狀態,這個對象是你用來啓動它的第一個地方。

  3. 根據需要配線一切。 Actor啓動時按需打開連接(並根據需要緩存)。我發現我經常這麼做 - 當連接不再工作時,我讓演員失敗。主管將重新啓動Actor,它將重新創建所有連接。

一些很重要的事情要記住:

  • Actor模型的目的是使演員不連續運行 - 他們只在有提供給他們的消息中運行。如果將一個消息監聽器添加到Actor中,則實質上是添加可以訪問該actor的新線程。這可能是一個問題,如果你使用監督 - 重新啓動的演員可能泄漏該線程,這可能會導致演員不被垃圾收集。它也可能是一個問題,因爲它引入了一種競爭條件,並且演員的部分價值在於避免這種情況。
  • 從actor系統的角度來看,I/O的Actor是阻塞。如果您有太多的Actor在同一時間執行I/O操作,那麼您將耗盡Dispatcher的線程池並鎖定系統。
  • 給定的Actor實例可以在其整個生命週期內對許多不同的線程進行操作,但一次只能在一個線程上運行。這可能會讓一些消息傳遞系統感到困惑 - 例如,JMS的Spec聲明Session不會在多個線程上使用,而且許多JMS將其解釋爲「只能在啓動它的線程上運行」。您可能會看到由此產生的警告,甚至是例外。
  • 由於這些原因,我更喜歡使用非角色代碼來執行一些I/O操作。例如,我將有一個傳入消息偵聽器對象,它負責將JMS消息從隊列中取出,使用它們創建POJO消息,並將通知發送給Actor系統。或者,我將使用Actor,但將該actor放置在啓用了線程鎖定的自定義Dispatcher上。這可以確保Actor只能運行在特定的線程上,並且不會阻塞其他非I/O角色正在使用的系統。