Akka入门实例

Akka 是一个用 Scala 编写的库,用于简化编写容错的、高可伸缩性的 Java 和 Scala 的 Actor 模型应用。web

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 this

 

 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 对象spa

注意: 线程

  • Props(...)中不能始终传入同一个 actor 对象,例如 val lazy 或 object extends Actor 等单例工厂实现方式,这会和 AKKA 中 actor restart 机制冲突。 
  •  构造器参数不能是可变的(var),由于 call-by-name 块可能被其它线程调用,引发条件竞争。

Actor API
Actor trait 只定义了一个抽象方法,就是上面提到的 receive, 用来实现actor的行为。scala

若是当前 actor 的行为与收到的消息不匹配,则会调用 unhandled, 它的缺省实现是向actor系统的事件流中发布一条 akka.actor.UnhandledMessage(message, sender, recipient)。

另外,它还包括:

  • self 表明本actor的 ActorRef
  • sender 表明最近收到的消息的发送actor,一般用于下面将讲到的 回应消息中
  • supervisorStrategy 用户可重写它来定义对子actor的监管策略
  • context 暴露actor和当前消息的上下文信息