1. 程式人生 > >Akka官方文件2.5.17——什麼是Actor?

Akka官方文件2.5.17——什麼是Actor?

目錄

狀態

行為

郵箱

監督策略

什麼是Actor?

前面關於ActorSystem的一節,解釋了Actors如何形成層級結構,並且是構建應用的最小單元。本小節單獨看一個Actor,解釋在實現這樣一個Actor時的概念。相關細節的更深入參考,可參見Actors

一個Actor是狀態、行為、郵箱、子Actors以及監督策略的容器。所有這一切都被封裝在Actor引用中。一個值得注意的方面是Actors都有一個明確的生命週期,它們在沒有任何引用時也不會自動銷燬;當建立了一個Actor,那麼就是你的責任確保它最終會終止——同時也給了你當Actor終止時資源如何釋放的控制權限。

Actor引用

如下所述,為了從Actor模型中受益,一個Actor物件不應該暴露給外部。因此,通過Actor引用給外部物件使用,Actor引用可以任意且無限制的傳遞。這種劃分為內部和外部物件的方式使得對於所有操作保持透明性成為可能:如重啟一個Actor而不需要更新Actor引用,將真正的Actor物件放置在遠端機器上,在完全不同應用程式中傳送訊息。但最最重要的方面是不能檢視Actor的內部並從外部獲取Actor內部的狀態,除非Actor自身釋出這些資訊。

狀態

Actor物件通常包含了一些反映Actor可能處於的狀態的變數。這可能是一個顯式狀態機(比如使用FSM模組),或者一個計數器,一組listener集合,待處理請求等等。這些資料是Actor存在的意義,所以必須保護它們免受因其他Actor出錯而帶來的影響。好訊息是,Akka Actor從概念上來說,每個都擁有自己的輕量級執行緒,完全遮蔽了系統的其他部分。這意味著不需要使用鎖來進行同步訪問,而可以輕鬆的編寫Actor程式碼且不用擔心併發性。

在幕後,Akka會在一組執行緒上呼叫多個Actors,通常許多Actors共享一個執行緒,並且一個Actor的後續呼叫最終可能會在不同的執行緒上處理,Akka保證這種實現細節不會影響處理Actor狀態的單執行緒有效性。

因為內部狀態對於Actor的狀態至關重要,具有不一致的狀態是致命的。因此,當Actor失敗且被它的監督Actor重啟時,將會重新構建它的狀態,就像第一次建立Actor一樣。這是為了實現系統的自我修復能力。

可選的,通過持久化接收到的訊息並在重啟後重新執行,可以自動將Actor恢復到重啟前的狀態。(請參閱持久化

行為

每次處理訊息時,都會根據當前的Actor行為進行匹配。行為是指定義了在某時間點對訊息作出反應的函式,例如:如果客戶端已經授權則轉發請求,否則拒絕請求。這個行為可能會隨時間而發生改變,例如:不同的客戶端隨著時間的推移獲得授權,或者Actor會“宕機”然後又重新提供服務。這些改變通過將它們封裝在狀態變數中,然後通過行為的邏輯去讀取,或者函式本身在執行時自動切換來實現,查閱become

unbecome操作。然而,在Actor構造期間定義的初始行為是特殊的,因為每次重啟Actor都會將其行為重置為初始行為。

郵箱

一個Actor的目的是為了處理訊息,這些訊息從其他Actors(或者Actor系統外部)傳送給當前Actor。Actor郵箱是連線傳送者和接受者的部分:每個Actor有且只有一個郵箱,所有的傳送者的訊息都將會入隊。入隊按傳送操作的時間順序進行,這意味著由於隨機的分配執行緒對Actor進行處理,不同Actors傳送的訊息沒有明確的順序。另一方面,從同一個Actor向同一目標傳送的多個訊息將以相同的順序入隊。

有多種不同的郵箱實現策略,預設情況下是FIFO佇列:訊息的處理順序與它們入隊的順序相同。這通常是一個好的預設方式,但是應用程式可能需要優先處理部分訊息。在這種情況下,一個優先順序郵箱的入隊操作不會總是在佇列末,而是根據訊息的優先順序排在指定位置,甚至可能在佇列前面。當用這樣一個佇列時,處理訊息的順序通常由佇列自己的演算法定義,而不是FIFO。

Akka和其他一個Actor模型的不同之處在於,當前行為必須處理下一個出列的訊息,沒有掃描郵箱並找到下一個匹配的訊息功能。無法處理訊息通常被視為失敗,除非顯式的覆蓋該行為。

子Actors

每一個Actor都可能是一個監督者:如果它建立子Actor來委派子任務,它將會自動監督它們。子Actors會儲存在該Actor上下文中的列表中,並且該Actor可以訪問它們。通過建立 context.actorOf(...)或者停止 context.stop(...)來完成對列表的修改。實際的建立和停止操作會以非同步的方式在幕後執行,所以不會阻塞它們的監督者。

監督策略

Actor的最後一部分是子Actor的錯誤處理策略。通過對每個錯誤運用監督和監控中的某個策略,Akka可以對其進行透明處理。因為策略是Actor系統結構的基礎,所以一旦建立,就無法在執行時更改。

考慮到每個Actor有且僅有一種策略,這意味著如果Actor的子節點需要不同的策略進行處理時,那麼這些子節點應該按照不同的策略進行分組,並與不同的中間監督者進行匹配。根據將任務劃分為子任務的形式,再次優先考慮Actor系統的層次結構。

當Actor終止

一旦一個Actor終止時,比如錯誤沒有被捕捉並重啟,自行停掉自己,被監督者停掉等等。這時會釋放它的資源,將所有剩餘的未處理訊息轉移到系統的“dead letter郵箱”,然後當作DeadLetters傳送到EventStream。然後,Actor引用中的郵箱會被替換為系統郵箱,訊息直接重定向為DeadLetters傳送到EventStream。這是在盡力而為的基礎上完成的,所以不要依賴這種機制去構建“guaranteed deliver”