2013-05-19 72 views
2

我想創建可以從文件系統中提供資源的演員。理想情況下[1]我希望每個目錄和每個文件都有一個actor。但我不想創建整個actor樹層次結構,因爲我希望儘可能節省內存和資源。懶洋洋地創建Akka演員層次結構

據我所知,一名演員只能在其父母存在的情況下創建。懶惰地創建這些層次結構的最好方法是什麼?有沒有一個鉤子可以用來捕捉失敗並快速創建演員層次結構,並且有效地這樣做?

通過這樣做,我可以發送fetch,update,delete,...消息給演員,而阿卡演員系統將會處理同步問題。這然後可以擴展到更復雜的演員的行爲後來隨着虛擬文件或者這樣的觀念......

一些可能的解決方案,我能想到的:

  1. 運行context.actorFor(path)如果返回死信郵箱,嘗試創建演員層次結構。這聽起來不是一個好的解決方案。
  2. 將消息發送給根演員,並使用getOrCreateChild方法將其轉發給其子代。但是,這可能是低效的? (或者這就是阿卡本身在幕後做的事情......(我應該看看))
  3. 不這樣做,只是創建一個演員,委派每個消息到一個目錄演員爲飛行創建的每個目錄所請求的文件在堆棧溢出問題"on demand actor get or else create"的答案中解釋。這對於捕獲目錄刪除語義來說不是很好。 (會更有效率嗎?)

[1]我不確定這是否理想,但我認爲我應該先嚐試這種方法。另一種方法是爲每個目錄創建一個actor並將其存儲在散列映射中。

+0

我剛剛發現了AKKA代理商。我想知道是否爲了映射文件系統(爲了Web服務器的目的),代理將不會更好,因爲我期望在這個數據結構上的讀取更爲常見。這些文件很少,我不確定那些文件在哪裏。沒有說明Agent有多少內存,並且改變Agent的行爲似乎並不容易。一個人的應用程序也需要從URIs-> Agents –

回答

2

首先,演員非常輕巧。您可以讓數百萬人在JVM中運行,併爲演員本身留下極小的空間。顯然,如果演員有一些自定義狀態可以是大內存明智的,但是演員本身的佔用空間非常小,則這會發生變化。

現在,如果您仍然想要懶惰地實現它們,一種方法可能是讓單個文件或文件夾主角接收所有初始呼叫。這個actor檢查系統,看看是否已經存在一個actor來爲請求所針對的任何文件夾或文件提供請求。如果沒有,主人創建它,然後將消息轉發給它。如果是這樣,它只是將消息轉發給它。由於ActorSystem本身將爲您保留所有ActorRefs,因此無需在內存中保留散列表,併爲您提供查找方法。你只需要一個將文件名/路徑等同於演員姓名的方法。主的過於簡單的例子看起來是這樣的:

case class Fetch(path:String) 
class FileMaster extends Actor{ 
    def receive = { 
    case msg @ Fetch(path) => 
     val ref = lazyFindActor[FileHandler](path) 
     ref.forward(msg) 
    } 

    def lazyFindActor[T <: Actor: Manifest](name:String) = { 
    val ref = context.actorFor(name) 
    if (ref == context.system.deadLetters){ 
     context.actorOf(Props[T], name) 
    } 
    else{ 
     ref 
    } 
    } 
} 

所有lazyFindActor所做的是檢查是否已經創建了該路徑的演員,並開始。如果是這樣,它轉發給它。如果不是(並且與deadLetters比較,不幸的是,我沒有看到更好的方法來檢查演員是否存在),它在主人的監督下創建一個然後轉發給它。下一次進入相同的路徑時,它將使用預先存在的Actor

您可能需要做一些工作,從文件路徑語法翻譯成可用於演員姓名的東西(因爲akka已經爲演員路徑使用了類似結構的分層文件路徑),但我不是100對這一點肯定。只是想向你拋出一個高層次的概念,看看你是否在尋找這個概念。

+0

來管理地圖,這要歸功於以下代碼:-)看起來您正在將可能的解決方案概要1和3相結合。我在問題描述中添加了這些內容。你不用像我想的那樣在3中使用散列表,但是你使用了命名層次結構,其中名稱可以包含斜槓。 ---我可以看到文件路徑和akka路徑相對應的優點是,對文件路徑的調用可以直接調用正確的actor,以便目錄可以包含文件actor。如果一個人按照你的建議行事,那麼你需要始終通過根目錄創建者來創建目錄。 –

+1

我不一定會將主人視爲問題。在演員系統中,通過多個參與者路由消息是非常普遍的模式,每個參與者在服務該消息的整個流程中服務於不同的目的。在這裏,主人的責任是始終確保適當的參與者實例正在處理消息。另外,如果您擔心會發生兩個郵箱匹配來處理一條消息,您可以將主設備重寫爲定製的Akka'Router'。路由器完全跳過郵箱。 – cmbaxter

+0

非常感謝'Router'上的提示。我會研究一下。 –