Akka入門實例


Akka 是一個用 Scala 編寫的庫,用於簡化編寫容錯的、高可伸縮性的 Java 和 Scala 的 Actor 模型應用。

Actor模型並非什么新鮮事物,它由Carl Hewitt於上世紀70年代早期提出,目的是為了解決分布式編程中一系列的編程問題。其特點如下:

  • 系統中的所有事物都可以扮演一個Actor
  • Actor之間完全獨立
  • 在收到消息時Actor所采取的所有動作都是並行的,在一個方法中的動作沒有明確的順序
  • Actor由標識和當前行為描述
  • Actor可能被分成原始(primitive)和非原始(non primitive)類別
  • 非原始Actor有
    • 由一個郵件地址表示的標識
    • 當前行為由一組知識(acquaintances)(實例變量或本地狀態)和定義Actor在收到消息時將采取的動作組成
  • 消息傳遞是非阻塞和異步的,其機制是郵件隊列(mail-queue)
  • 所有消息發送都是並行的

首先通過一個簡單的例子快速簡單的介紹AKKA actor 是如何實現和使用的。

創建簡單的 Actor 模式應用程序,定義EchoServer如下代碼所示,EchoServer類繼承 AKKA 中的 Actor 類,定義偏函數(Partial Function)receive,receive 函數中通過模式匹配(Pattern Match)實現程序邏輯。

 

 1 package foo
 2 
 3 import akka.actor.{ Actor, ActorSystem, Props}
 4 import akka.event.Logging
 5 
 6 object test extends App {
 7     
 8 val system = ActorSystem()
 9 
10 class EchoServer extends Actor {
11   val log = Logging(context.system,this)
12   def receive = {
13      case msg: String => println("echo " + msg)
14   }
15 }
16 
17 val echoServer = system.actorOf(Props[EchoServer])
18 echoServer ! "hello!"

如上代碼所示,通過 AKKA 中的 ActorSystem 對象的 actorOf 方法創建上面的 EchoServer類對象實例,返回AKKA 中的 ActorRef 類型的 EchoServer對象, echoServer對象是 EchoServer類對象實例的引用,通過 echoServer對象可以向 EchoServer類對象實例發送消息。

注意: 

  •  如果 receive 方函數中不存在默認匹配,則會向 ActorSystem 的事件消息流(Event Stream)發送akka.actor.UnhandledMessage(message,sender,recipient)消息。 
  •  ActorRef 類型的對象是不可變的和可序列化的,可以在網絡中進行傳輸,作為遠程對象使用,具體的操作還是在本地的 Actor 類對象。
  •  Actor 對象的名稱可以在創建時省略;如果不省略 actor 對象的名稱,那么在同一個父 actor 對象下子actor 的名稱必須唯一。 
  • Actor 對象的名稱不能為空,並且不能是以‘$’開頭的字符串。

創建帶參數構造器 Actor 

 

 1 package foo
 2 
 3 import akka.actor.{ Actor, ActorSystem, Props}
 4 import akka.event.Logging
 5 
 6 object test extends App {
 7     
 8 val system = ActorSystem()
 9 
10 class Actor2(name:String) extends Actor {
11   val log = Logging(context.system,this)
12   def receive = {
13     case "hello" => log.info(name + " echo hello " )
14     case _ => log.info(name + " unknown msg")
15   }
16 }
17 val actor2 = system.actorOf(Props(new Actor2("tom")))
18 
19 actor2 ! "hello"

如上面代碼所示,Actor2 類帶有參數的構造函數,這種情況下無法使用Props[Actor2]的方式創建 actor2 對象。可以采用 call-by-name塊(參考scala相關內容)的方式創建 actor2 對象

注意: 

  • Props(...)中不能始終傳入同一個 actor 對象,例如 val lazy 或 object extends Actor 等單例工廠實現方式,這會和 AKKA 中 actor restart 機制沖突。 
  •  構造器參數不能是可變的(var),因為 call-by-name 塊可能被其它線程調用,引起條件競爭。

Actor API
Actor trait 只定義了一個抽象方法,就是上面提到的 receive, 用來實現actor的行為。

如果當前 actor 的行為與收到的消息不匹配,則會調用 unhandled, 它的缺省實現是向actor系統的事件流中發布一條 akka.actor.UnhandledMessage(message, sender, recipient)。

另外,它還包括:

  • self 代表本actor的 ActorRef
  • sender 代表最近收到的消息的發送actor,通常用於下面將講到的 回應消息中
  • supervisorStrategy 用戶可重寫它來定義對子actor的監管策略
  • context 暴露actor和當前消息的上下文信息


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM