[系統架構] AKKA工作原理

1.02^365的成長裂變發表於2018-08-08

Akka工作原理

Akka

Akka中的角色

  • ProducerActor(StudentActor)
  • ConsumerActor(TeacherActor,onReceive方法接收訊息)
  • ActorRef(tell方法,傳送訊息給MessageDispatcher訊息派發器)
  • ActorSystem(actorOf方法,建立ActorRef,ActorRef就是ConsumerActor的Proxy)
  • MailBox
  • Dispatcher
  • Message

Akka工作流程

  1. ProducerActor(StudentActor)建立了一個叫ActorSystem的東西。
  2. 他通過ActorSystem來建立了一個叫ActorRef的物件。QuoteRequest訊息就是傳送給ActorRef的(它是TeacherActor的一個代理)
  3. ActorRef將訊息傳送給Dispatcher
  4. Dispatcher將訊息投遞到目標Actor的郵箱中。
  5. 隨後Dispatcher將Mailbox扔給一個執行緒去執行(這點下節會重點講到)
  6. MailBox將訊息出隊並最終將其委託給真實的Teacher Actor的接收方法去處理。

建立ActorSystem

ActorSystem是進入到Actor的世界的一扇大門。通過它你可以建立或中止Actor。甚至還可以把整個Actor環境給關閉掉。

另一方面來說,Actor是一個分層的結構,ActorSystem之於Actor有點類似於java.lang.Object或者scala.Any的角色——也就是說,它是所有Actor的根物件。當你通過ActorSystem的actorOf方法建立了一個Actor時,你其實建立的是ActorSystem下面的一個Actor。

ActorSystem

建立ActorRef(ConsumerActor(TeacherActor)的Proxy)

ActorRef myActor = system.actorOf(Props.create(MyUntypedActor.class), “myactor”);

actorOf是ActorSystem中建立Actor的方法。但是正如你所看到的,它並不會返回我們所需要的TeacherActor。它返回的是一個ActorRef。

這個ActorRef扮演了真實的Actor的一個代理的角色。客戶端並不會直接和Actor通訊。這也正是Actor模型中避免直接訪問TeacherActor中任何的自定義/私有方法或者變數的一種方式。

再重複一遍,訊息只會傳送給ActorRef,最終才會到達真正的Actor。你是絕對無法直接和Actor進行通訊的。如果你真的找到了什麼拙劣的方式來直接通訊,大家會恨你入骨的。

將訊息傳送給代理

還是隻有一行程式碼。你只需告訴說把QuoteRequest訊息傳送到ActorRef就好了。Actor中的這個告訴的方式就是一個!號。(ActorRef中確實也有一個tell方法,不過它只是把這個呼叫委託給了!號)

分發器及郵箱

ActorRef把訊息處理功能委託給了Dispatcher。實際上,當我們建立ActorSystem和ActorRef的時候,就已經建立了一個Dispatcher和MailBox了。我們來看下它們是幹什麼的。

郵箱

每個Actor都有一個MailBox(後面會介紹一種特殊的情況)。在我們這個比喻當中,每個老師也有一個郵箱。老師得去檢查郵箱並處理訊息。在Actor的世界中,則是另一種形式——郵箱一有機會就會要求Actor去完成自己的任務。

同樣的,郵箱裡也有一個佇列來以FIFO的方式來儲存並處理訊息——它和實際的郵箱還有點不同,真實的郵箱新的信總是在最上面的。

分發器

Dispatcher會完成一些很酷的事。從它的角度來看,它只是從ActorRef中取出一條訊息然後將它傳給了MailBox。但是,在這後面發生了一件不可意義的事情:

Dispatcher會封裝一個ExecutorService(ForkJoinPoll或者ThreadPoolExecutor)。它把MailBox扔到ExecutorService中去執行。

是的。我們看到MailBox中包含了佇列裡面的訊息。由於Executor得去執行MailBox,所以它得是一個Thread型別。是的沒錯。MailBox的宣告及構造器就是這樣的。

ConsumerActor(TeacherActor)

當MailBox的run方法執行的時候,它會從佇列中取出一條訊息,然後將它傳給Actor去處理。

當你把訊息傳給ActorRef的時候,最終呼叫的實際是目標Actor裡面的一個receive方法。

TeacherActor只是一個很簡單的類,它有一個名言的列表,而receive方法很明顯就是用來處理訊息的。

TeacherActor的receive方法的模式匹配只會匹配一種訊息——QuoteRequest (事實上,模式匹配中最好匹配下預設的情況,不過這個就說來話長了)

receive方法做的就是

  1. 匹配QuoteRequest的模式
  2. 從名言列表中隨機選取一條
  3. 構造出一個QuoteResponse
  4. 將QuoteResponse列印到控制檯上

參考文章:

相關文章