1. 程式人生 > >Akka中Actor介紹《seventeen》譯

Akka中Actor介紹《seventeen》譯

What is an Actor?

上一節關於Actor Systems的部分解釋了actor如何形成層次結構,並且是構建應用程式時的最小單元。本節將單獨檢視一個這樣的actor,解釋在實現它時的概念。有關所有細節的更深入參考,請參閱Actors

Actor是State,Behavior,Mailbox,Child Actors和Supervisor Strategy的容器。所有這些都封裝在Actor Reference之後。一個值得注意的方面是演員有一個明確的生命週期,當不再被引用時它們不會被自動銷燬;在建立一個之後,您有責任確保它最終也會被終止 - 這也可以控制當Actor終止時如何釋放資源。

Actor Reference

如下所述,需要從外部遮蔽actor物件以便從actor模型中受益。因此,使用actor Reference將actor表示到外部使用,actor Reference是可以自由且無限制地傳遞的物件。這分為內部和外部物件,可以實現所有所需操作的透明性:重新啟動actor而無需在其他地方更新引用,將實際的actor物件放在遠端主機上,向完全不同的應用程式中的actor傳送訊息。但最重要的方面是,除非演員本身不明智地釋出這些資訊,否則無法檢視演員內部並從外部獲取其狀態。

State

Actor物件通常包含一些反映actor可能處於的狀態的變數。這可以是顯式狀態機(例如使用FSM模組),也可以是計數器,監聽器集,待處理請求等。這些資料是讓演員有價值的東西,必須保護他們免受其他演員的腐敗。好訊息是,Akka Actor在概念上每個都有自己的輕量級執行緒,完全遮蔽了系統的其他部分。這意味著您不必使用鎖來同步訪問,而是可以編寫您的actor程式碼而不必擔心併發性。

在幕後,Akka將在一組真實執行緒上執行多組actor,通常許多actor共享一個執行緒,並且一個actor的後續呼叫最終可能會在不同的執行緒上進行處理。Akka確保此實現細節不會影響處理actor狀態的單執行緒。

因為內部狀態對於Actor的操作至關重要,所以具有不一致的狀態是致命的。因此,當actor失敗並由其主管重新啟動時,將從頭開始建立狀態,就像首次建立actor一樣。這是為了實現系統自我修復的能力。

通過持久儲存收到的訊息並在重新啟動後重放它們,可以自動將actor的狀態恢復到重啟前的狀態(請參閱“ Persistence”)。

Behavior

每次處理訊息時,都會根據actor的當前behavior進行匹配。behavior是指定義在該時間點對訊息作出反應的動作的函式,例如,如果客戶端被授權則轉發請求,否則拒絕它。此行為可能會隨時間而改變,例如因為不同的客戶端會隨著時間的推移獲得授權,或者因為參與者可能會進入“服務中斷”模式並稍後返回。這些更改是通過在狀態變數中對它們進行編碼來實現的,這些狀態變數是從行為邏輯中讀取的,或者函式本身可以在執行時被換出,請參閱變為和不成熟的操作。但是,在構造actor物件期間定義的初始行為是特殊的,因為重新啟動actor會將其行為重置為此初始行為。

Mailbox

Actor的目的是處理訊息,這些訊息從其它Actor(或Actor系統外部)傳送。連線傳送者和接收者的片段是Actor的郵箱:每個Actor只有一個郵箱,所有發件人都將其郵件排入佇列。入隊以傳送操作的時間順序發生,這意味著由於跨執行緒分配actor的明顯隨機性,從不同的actor傳送的訊息可能在執行時沒有定義的順序。另一方面,從同一個actor向同一目標傳送多個訊息將以相同的順序排列它們。

有不同的郵箱實現可供選擇,預設為FIFO:由actor處理的訊息的順序與它們排隊的順序相匹配。這通常是一個很好的預設設定,但應用程式可能需要優先處理某些訊息而不是其他訊息。在這種情況下,優先順序郵箱不會總是排在最後,而是排列在訊息優先順序給定的位置,甚至可能位於前面。在使用這樣的佇列時,處理的訊息的順序自然會由佇列的演算法定義,並且通常不是FIFO。

Akka與其他一些actor模型實現的不同之處在於,當前行為必須始終處理下一個出列的訊息,沒有掃描郵箱以查詢下一個匹配的訊息。無法處理訊息通常會被視為失敗,除非覆蓋此行為。

Child Actors

每個Actor都可能是一個主管:如果它建立子任務來委派子任務,它將自動監督它們。子項列表儲存在actor的上下文中,並且actor可以訪問它。通過建立(context.actorOf(...))或停止(context.stop(child))子項來完成對列表的修改,並立即反映這些操作。實際的建立和終止操作以非同步方式在幕後發生,因此它們不會“阻止”他們的主管。

Supervisor Strategy

Actor的最後一部分是處理其子女故障的策略。然後,Akka透明地完成故障處理,對每個進入的故障應用監督和監控中描述的策略之一。由於此策略是Actor系統結構的基礎,因此一旦建立了Actor,就無法更改。

考慮到每個Actor只有一個這樣的策略,這意味著如果不同的策略適用於一個Actor的各個孩子,那麼這些孩子應該被分組在具有匹配策略的中間監督者之下,再次優先考慮Actor系統的結構。將任務拆分為子任務。

When an Actor Terminates

一旦一個actor終止,自行停止或被其主管停止,它將釋放其資源,將所有剩餘的訊息從其郵箱中排放到系統的“死信郵箱”中。將它們作為DeadLetters轉發到EventStream。然後,使用系統郵箱在actor引用中替換郵箱,將所有新訊息重定向到EventStream作為DeadLetters。儘管如此,這是在盡力而為的基礎上完成的,因此不要依賴它來構建“保證交付”。

不僅僅是默默地轉儲訊息的原因受到了我們的測試的啟發:我們在轉發死信的事件總線上註冊了TestEventListener,並且會在收到的每封死信中記錄警告 - 這對解密很有幫助更快地測試失敗。可以想到,該特徵也可用於其他目的。