Actor References, Paths and Addresses 20
原文:https://doc.akka.io/docs/akka/2.5/general/addressing.html
在這裡描述瞭如何在可能分佈的actor系統中識別和定位actor。它與Actor系統形成內在監督層次結構以及Actor之間的通訊相對於它們在多個網路節點上的放置是透明的中心思想聯絡在一起。
上圖顯示了Actor系統中最重要的實體之間的關係,請繼續閱讀詳細資訊。
What is an Actor Reference?
actor reference是ActorRef的子型別,其最重要的目的是支援向它所代表的actor傳送訊息。每個Actor都可以通過self欄位訪問其(local)引用,包括對於傳送給其他actor的所有訊息。在訊息處理期間,actor可以通過sender()方法訪問表示當前訊息的傳送者的引用。
根據actor系統的配置,支援幾種不同型別的actor引用:
- 純粹的本地actor引用由未配置為支援網路功能的actor系統使用。如果通過網路連線傳送到遠端JVM,這些actor引用將不起作用。
- 啟用遠端處理時的本地actor引用由actor系統使用,該系統支援那些表示同一JVM中的actor的引用的網路功能。為了在傳送到其他網路節點時也可以訪問,這些引用包括協議和遠端定址資訊。
- 存在用於路由器的本地Actor引用的子型別(即,在路由器特徵中混合的角色)。它的邏輯結構與前面提到的本地引用相同,但是向它們傳送訊息直接傳送給它們的一個子節點。
- 遠端actor引用表示使用遠端通訊可訪問的actor,即向它們傳送訊息將透明地序列化訊息並將它們傳送到遠端JVM。
- 有幾種特殊型別的actor引用,其行為類似於本地actor引用,用於所有實際目的:
- PromiseActorRef是Promise的特殊表示,目的是由Actor的響應完成。akka.pattern.ask建立此actor reference。
- DeadLetterActorRef是dead信服務的預設實現,Akka將所有目的地關閉或不存在的訊息路由到該服務。
- EmptyLocalActorRef是Akka在查詢不存在的本地actor路徑時返回的內容:它等同於DeadLetterActorRef,但它保留了它的路徑,以便Akka可以通過網路傳送它並將其與該路徑的其他現有actor引用進行比較,其中可能是在Actor銷燬前獲得的。
- 然後有一些一次性的內部實現,可能你永遠不會真的可能啊到:
- 有一個Actor引用不代表一個Actor,但只是作為根守護者的偽監督者,我們稱之為“the one who walks the bubbles of space-time”。
- 在實際啟動actor建立工具之前啟動的第一個日誌記錄服務是一個假的actor引用,它接受日誌事件並將它們直接列印到標準輸出;它是Logging.StandardOutLogger。
What is an Actor Path?
由於Actor是以嚴格的分層方式建立的,因此存在一個獨特的Actor名稱序列,通過遞迴地跟隨子和父母之間的監督連結向下朝向Actor系統的根來給出。此序列可以看作是檔案系統中的資料夾,因此我們採用名稱“path”來引用它,儘管actor層次結構與檔案系統層次結構有一些根本區別。
一個actor路徑包含一個anchor,它標識了actor系統,然後是路徑元素的串聯,從根守護者到指定的actor;path元素是遍歷的actor的名稱,並用斜槓分隔。
What is the Difference Between Actor Reference and Path?
actor reference指定一個actor,reference的生命週期與actor的生命週期相匹配;一個actor path代表一個名字,該名字可能是也可能不是由Actor在的位置,而且path本身沒有生命週期,它永遠不會變得無效。您可以在不建立actor的情況下建立actor path,但是如果不建立相應的actor,則無法建立actor reference。
您可以建立一個actor,終止它,然後建立一個具有相同actor path的新actor。新建立的Actor是的新化身。這不是同一個Actor。對舊化身的Actor引用對新的化身無效。傳送到舊actor 應用的訊息即使具有相同的路徑,也不會被傳遞給新的化身。
Actor Path Anchors
每個actor路徑都有一個地址元件,描述了可以訪問相應actor的協議和位置,然後是從根目錄開始的層次結構中actor的名稱。例子是:
這裡,akka.tcp是2.4版本的預設遠端傳輸;其他運輸工具是可插拔的。主機和埠部分的解釋(即示例中的host.example.com:5678)取決於所使用的傳輸機制,但它必須遵守URI結構規則。
Logical Actor Paths
通過遵循父監督連結到根監護人獲得的唯一路徑稱為logical actor path。此路徑與actor的建立祖先完全匹配,因此只要設定了actor系統的遠端配置(以及路徑的地址元件),它就完全確定了。
Physical Actor Paths
雖然邏輯actor路徑描述了一個actor系統內的功能位置,但是基於配置的遠端部署意味著可以在不同於其父節點的網路主機上建立actor,即在不同的actor系統內。在這種情況下,遵循來自根監護人的actor路徑需要遍歷網路,這是一項代價高昂的操作。因此,每個actor也有一個物理路徑,從實際actor物件所在的actor系統的根守護者開始。在查詢其他actor時使用此路徑作為傳送方引用將允許它們直接回復此actor,從而最大限度地減少路由引起的延遲。
一個重要方面是物理actor路徑從不跨越多個actor系統或JVM。這意味著如果遠端監督其祖先之一,則演員的邏輯路徑(監督層級)和物理路徑(演員部署)可能會發散。
How are Actor References obtained?
如何獲得actor引用有:通過建立actor或查詢它們,後者的功能來自於從具體actor路徑建立actor引用和查詢邏輯actor層次結構的兩種方式。
Creating Actors
Actor系統通常是通過使用ActorSystem.actorOf方法在守護者actor下建立actor,然後在建立的actor中使用ActorContext.actorOf來生成actor樹來啟動的。這些方法返回對新建立的actor的引用。每個Actor都可以直接訪問(通過其ActorContext)其父級,自身及其子級的引用。這些引用可以在訊息中傳送給其他Actor,使他們能夠直接回復。
Looking up Actors by Concrete Path
此外,可以使用ActorSystem.actorSelection方法查詢actor引用。該選擇可以用於與所述Actor進行通訊,並且在傳送每個訊息時查詢與該選擇相對應的Actor。
要獲取繫結到特定actor的生命週期的ActorRef,您需要向actor傳送訊息(例如內建Identify訊息)並使用actor的回覆的sender()引用。
Absolute vs. Relative Paths
除了ActorSystem.actorSelection之外,還有ActorContext.actorSelection,它在任何actor中都可用作context.actorSelection。這會產生一個actor selection,就像它在ActorSystem上的雙胞胎一樣,但不是從actor樹的根開始查詢路徑,而是從當前的actor開始。由兩個點(“..”)組成的路徑元素可用於訪問父actor。例如,您可以向特定的兄弟傳送訊息:
也可以通常的方式在上下文中查詢絕對路徑,即
將按預期工作。
Querying the Logical Actor Hierarchy
由於actor系統形成類似層次結構的檔案系統,因此可以採用與Unix shell支援的相同方式匹配路徑:您可以用萬用字元(*«*»*和«?»)替換(部分)路徑元素名稱制定一個可以匹配零個或多個實際Actor的選擇。因為結果不是單個actor引用,所以它具有不同型別的ActorSelection,並且不支援ActorRef執行的完整操作集。可以使用ActorSystem.actorSelection和ActorContext.actorSelection方法制定選擇,並支援傳送訊息:
將msg傳送給包括當前Actor在內的所有兄弟姐妹。對於使用actorSelection獲得的引用,完成監督層次結構的遍歷以便執行訊息傳送。由於與訊息選擇匹配的確切Actor集可能會在訊息進入收件人時發生變化,因此無法觀看選擇的生動性變化。為了做到這一點,通過傳送請求並收集所有答案,提取發件人參考,然後觀察所有發現的具體Actor來解決不確定性。在將來的版本中可以改進這種解決選擇的方案。
Actor Reference and Path Equality
ActorRef的相等性與ActorRef對應於目標actor化身的意圖相匹配。當兩個actor引用具有相同的路徑並指向相同的actor化身時,它們相等。指向已終止的actor的引用不會比較指向具有相同路徑的另一個(重新建立的)actor的引用。請注意,由失敗引起的actor的重啟仍然意味著它是相同的actor化身,即對於ActorRef的使用者不可見重啟。
如果您需要跟蹤集合中的actor引用並且不關心確切的actor化身,則可以使用ActorPath作為鍵,因為在比較actor路徑時不考慮目標actor的識別符號。
Reusing Actor Paths
當Actor被終止時,它的引用將指向dead信郵箱,DeathWatch將釋出其最後的過渡,並且通常不會再次恢復生命(因為Actor生命週期不允許這樣)。雖然有可能在以後建立一個具有相同路徑的actor ,由於在不保持所有可用的actor的集合可用的情況下無法強制執行相反的操作。
在非常具體的情況下做這件事可能是正確的,但要確保將這個處理精確地限制在Actor的主管,因為這是唯一可以可靠地檢測到名稱的正確登出的Actor,在此之前建立新的孩子會失敗。
在測試期間,當測試物件依賴於在特定路徑上例項化時,也可能需要它。在這種情況下,最好模擬其主管,以便它將Terminated訊息轉發到測試過程中的適當點,使後者能夠等待正確的名稱登出。
The Interplay with Remote Deployment
當actor建立子節點時,actor系統的部署者將決定新actor是在同一個JVM中還是在另一個節點上。在第二種情況下,Actor的建立將通過網路連線觸發,以在不同的JVM中發生,從而在不同的Actor系統中發生。遠端系統將新actor放置在為此目的保留的特殊路徑下方,新actor的主管將是遠端actor引用(表示觸發其建立的actor)。在這種情況下,context.parent(supervisor引用)和context.path.parent(actor的路徑中的父節點)不代表同一個actor。但是,在主管中查詢孩子的名字會在遠端節點上找到它,保留邏輯結構,例如傳送到未解析的actor引用時。
What is the Address part used for?
通過網路傳送actor引用時,它由其路徑表示。因此,該路徑必須完全編碼將訊息傳送給底層Actor所需的所有資訊。這是通過在路徑字串的地址部分中編碼協議,主機和埠來實現的。當actor系統從遠端節點接收actor路徑時,它會檢查該路徑的地址是否與該actor系統的地址匹配,在這種情況下,它將被解析為actor的本地引用。否則,它將由遠端actor引用表示。
Top-Level Scopes for Actor Paths
路徑層次結構的根目錄是根守護者,在該守護者之上找到所有其他actor;它的名字是 ”/”。下一級包括以下內容:
- “/ user”是所有使用者建立的頂級Actor的守護者;使用ActorSystem.actorOf建立的actor位於此下方。
- “/ system”是所有系統建立的頂級Actor的守護者,例如記錄在actor系統開始時由配置自動部署的偵聽器或actor。
- “/ deadLetters”是dead letter actor,它是傳送給已停止或不存在的actor的所有訊息被重新路由的地方(盡力而為:即使在本地JVM中也可能丟失訊息)。
- “/ temp”是所有系統建立的臨時Actor的守護者,例如:那些在ActorRef.ask的實現中使用的。
- “/ remote”是一個人為路徑,所有其主管是遠端參與者的Actor都在其下面。
為這樣的Actor構建名稱空間的需要源於一箇中心且非常簡單的設計目標:層次結構中的所有東西都是Actor,所有Actor都以相同的方式運作。因此,您不僅可以查詢您建立的Actor,還可以查詢系統監護人並向其傳送訊息(在這種情況下,它將盡職盡責地丟棄)。這個強大的原則意味著沒有要記住的怪癖,它使整個系統更加統一和一致。
如果您想了解有關Actor系統頂層結構的更多資訊,請檢視The Top-Level Supervisors。
原文:https://doc.akka.io/docs/akka/2.5/general/addressing.html
未完待續!