1. 程式人生 > >AKKA文件(java版)—什麼是角色

AKKA文件(java版)—什麼是角色

原文: http://doc.akka.io/docs/akka/2.3.5/general/actors.html 譯者:Vitas
2.3 什麼是角色?
前面角色系統一節介紹了一群角色如何形成一個層次結構,並且介紹了角色是構建應用程式的最小單位。本節我們將角色拿出來單獨介紹,解釋一些你在使用它的過程中可能遇到的概念。對於一些更深入的細節,將會在後面的章節中詳細介紹。
你可以將角色想象成一個容器,它其中包括狀態,行為,一個信箱,子角色以及一個監管策略。所有這些都封裝在一個角色引用中。本節的最後介紹一個角色什麼時候終結。


2.3.1 角色引用
如下所述,為了更好的發揮角色模式的優勢,一個角色物件需要與外部隔離。因此,在外部通過一個角色引用來表示角色物件,這些角色物件引用可以自由的傳遞而不受約束。這種將物件劃分為內部物件和外部引用的好處是可以使下列操作透明化:重啟一個角色不需要更新角色引用,角色可以在遠端機器上,可以通過完全不同的應用來給角色發訊息。並且這樣做最重要的好處是,外部的物件永遠無法得到角色內部的狀態,除非角色不明智的公開了它的資訊。
2.3.2 狀態
角色物件通常都包含一些變數來表明它當下處於哪個狀態。這些變數可以是顯示的狀態機(例如,使用fsm-scala模型),也可以是一個計數器,一組監聽器,甚至等待掛起等。正是這些狀態資料使得角色有價值,因此必須保護它們不被其他的角色破壞。好訊息是從概念上來講每個Akka角色物件都有它自己的輕量級執行緒,而這個執行緒是與系統的其他部分完全隔離的。這也就意味著你可以放心大膽的寫你的角色程式碼而不用考慮併發的同步問題。
在後臺Akka會有一系列的真實執行緒來執行這一系列的角色,如有些情況下多個角色會共用一個執行緒。因而一個角色在接下來的呼叫中可能會被另一個不同的執行緒所處理。但是無論實現細節是怎麼樣的,Akka都能確保同時只有一個執行緒去改變角色的狀態。
角色的內部狀態對它的行為是至關重要的,如果出現狀態不一致將會產生致命的錯誤。因而,當一個角色失敗並被它的監管程式重啟時,它的狀態將被重新初始化。而這一點也使得系統有了自動恢復的能力。
可選擇地,一個角色也可以在重啟後通過重新處理那些老的訊息來恢復到它重啟之前的狀態(參考 persisitence-scala)。

2.3.3 行為
每次訊息的處理都會與角色當前的行為所匹配。行為指的是一個函式定義的在當前狀態下對一條訊息所要採取的行動。例如如果這個客戶端是經過認證的則轉發它的請求,否則拒絕。並且行為可能隨著時間的不同而變化,例如,某些客戶端可能在後來獲得了認證,或者角色先在“不在服務狀態”的模式後來又恢復服務了等等。這些變化可能是因為狀態變數的變化引起的,也可能是函式在執行時被換出引起的,參考become 和unbecome操作。然而,角色物件重啟後都會恢復到建構函式中初始化的行為。

2.3.4 信箱
角色的任務是處理來自其他角色(或者角色系統之外)發來的訊息。連通訊息傳送者和接受著的物件就是信箱:每個角色都有一個信箱,傳送者將訊息傳送到該信箱。訊息以傳送者傳送訊息的時間順序入隊,這也就意味著由於傳送者線上程上分佈的隨機性,來自不同角色的訊息在執行時沒有一個確定的入隊順序。但是同一個傳送者傳送的訊息順序是一定的。
這裡有很多不同的信箱實現方式可供選擇,預設的方式是FIFO:訊息被處理的順序和訊息入隊的順序相同。通常我們都選擇預設的實現方式,但是有些應用程式可能需要對一些訊息優先處理。在這種情況下,訊息入隊的時候就不一定是插在隊尾了,而是根據它的優先順序插入到對應的位置,優先順序特別高甚至可能直接插在隊頭。當使用這種佇列時,訊息被處理的順序決定於該佇列的實現演算法,並且通常不是FIFO.
Akka不同於其他角色模型實現的一個重要特徵是當前的行為必須挨個處理佇列裡的下一個訊息,它並不會去掃描信箱以得到一個匹配的訊息。無法處理訊息就會被認為是失敗,除非當前的行為是忽略此訊息。

2.3.5 子角色
每個角色都是一個潛在的監督員:一旦它建立了子角色並且賦予了它一個子任務,那麼它將自動監管這些子角色。角色在它的上下文環境(context)中維持著一個子角色列表,以便隨時訪問它們。角色通過建立(context.actorOF(…))或停止(context.stop(child))命令來修改這個列表。並且這個修改立馬就會生效。這個建立和終止命令是以非同步的方式實現的,所以它不會阻塞監督者。

2.3.6 監督者策略
角色最後一個功能是處理子角色的故障。故障處理對於使用者來說是透明的,對於發生的故障Akka都會自動的通過對應策略處理(監管和監測章節介紹)。 因為這些策略是構成角色系統的基礎,所以一旦角色被建立那麼這些故障處理策略將不可改變。
由於每個角色都只有一類故障處理策略,這也就意味著不同的子角色將會應用不同的策略。角色根據子角色所使用的故障處理策略將它們分組。根據任務被切分的子任務性質系統會不斷的重複這個分組過程。

2.3.7 什麼時候角色終止
一旦角色終止,如失敗後無法重啟,自己停止或者被監督者停止,那麼它將釋放它佔有的所有資源,並將它信箱中沒處理的訊息傳送到“死信件信箱”裡,然後“死信件信箱”將會把他們以DeadLetters的形式傳遞給EventStream. Actor引用中的信箱將會被一個系統信箱所取代,然後將所有訊息以DeadLetters的形式轉發給EventStream。雖然系統會盡最大努力來實現該訊息傳遞,但是我們不能依賴它來實現“有保證的傳遞”。
為什麼不選擇悄悄的將所有訊息傾倒出來,是基於我們下面的測試結果考慮:我們在事件匯流排(BUS)上註冊了測試事件監聽器(TestEventListener)。這裡事件匯流排即死信件被髮送到的地方。該監聽器將會對收到的每條死信件記錄一條警告日誌——這個可以幫助我們更快的檢測失敗。所以我們有理由相信這個特徵還將可以應用於其他目的。