http://www.cnblogs.com/hequn/articles/3764630.html
当程序的要求达到一台计算机的极限时,我们便需要将程序分布式化,让程序运行在多台计算机上。akka提供了remote actor用来构建分布式应用。
一、remote actor
1.Actor path
actor的路径设计采用了类似URL的形式,即scheme://domain:port/path。scheme代表协议(http或者ftp),domain代表域名或者ip地址,port代表端口,path代表路径。所以表示一个actor的路径是akka://ServerSys@10.102.141.77:2552/user/SomeActor。路径表示远程actor的主机ip是10.102.141.77,端口是2552,actorsystem是ServerSys,Actor的名字是SomeActor。通过Actor path,我们就可以远程访问一个actor,进而进行消息的传递。
2.Actor引用
当知道远程actor的url后,我们便可以远程访问一个actor。访问通过引用远程actor来实现。
val actor = context.actorFor("akka://actorSystemName@10.0.0.1:2552/user/actorName")
一旦得到了actor的引用,你就可以象与本地actor通讯一样与它进行通迅了
actor ! "Pretty awesome feature"
二、一个简单例子
有一个本地actor:LocalActor,一个远程actor:RemoteActor。我们要实现相互之间的通信。LocalActor向RemoteActor发送一个消息"Hi there",RemoteActor返回"Hi there got something"。
1.remote端。
remote端的目录结构如下
包含四个文件:application.conf,build.sbt,RemoteNodeApplication.scala,RemoteActor.scala
application.conf:
RemoteSys { akka { actor { provider = "akka.remote.RemoteActorRefProvider" } remote { transport = "akka.remote.netty.NettyRemoteTransport" netty { hostname = "192.168.178.192" port = 2552 } } } }
build.sbt
name := "RemotingExampleRemoteNode" version := "1.0" scalaVersion := "2.9.1" resolvers += "Typesafe Repository" at "http://repo.typesafe.com/typesafe/releases/" libraryDependencies ++= Seq( "com.typesafe.akka" % "akka-actor" % "2.0.2", "com.typesafe.akka" % "akka-remote" % "2.0.2", "com.typesafe.akka" % "akka-kernel" % "2.0.2" )
RemoteActor.scala
package org.akka.essentials.remotenode import akka.actor.Actor class RemoteActor extends Actor { def receive: Receive = { case message: String => // Get reference to the message sender and reply back sender.tell(message + " 192.168.178.192 got something") } }
RemoteNodeApplication.scala
package org.akka.essentials.remotenode import akka.kernel.Bootable import akka.actor.ActorSystem import akka.actor.Props import com.typesafe.config.ConfigFactory object RemoteActorSystem{ def main(args: Array[String]):Unit = { val system = ActorSystem("RemoteNodeApp", ConfigFactory.load().getConfig("RemoteSys")) val remoteActor = system.actorOf(Props[RemoteActor], name = "remoteActor") } }
sbt package进行编译,然后sbt run运行程序。
Remote端如果要以独立微内核的形式使用,RemoteNodeApplication.scala如下
RemoteNodeApplication.scala
package org.akka.essentials.remotenode import akka.kernel.Bootable import akka.actor.ActorSystem import akka.actor.Props import com.typesafe.config.ConfigFactory class RemoteNodeApplication extends Bootable { val system = ActorSystem("RemoteNodeApp", ConfigFactory .load().getConfig("RemoteSys")) def startup = { system.actorOf(Props[RemoteActor], name = "remoteActor") } def shutdown = { system.shutdown() } }
微内核的使用参考参考文献4.
2.Local端程序
目录结构同Remote端。也是包含四个文件:application.conf,build.sbt,LocalActor.scala,LocalNodeApplication.scala。
application.conf
LocalSys { akka { actor { provider = "akka.remote.RemoteActorRefProvider" } } }
build.sbt
name := "RemotingExampleLocalNode" version := "1.0" scalaVersion := "2.9.1" resolvers += "Typesafe Repository" at "http://repo.typesafe.com/typesafe/releases/" libraryDependencies ++= Seq( "com.typesafe.akka" % "akka-actor" % "2.0.2", "com.typesafe.akka" % "akka-remote" % "2.0.2", "com.typesafe.akka" % "akka-kernel" % "2.0.2" )
LocalActor.scala
package org.akka.essentials.localnode import akka.actor.Actor import akka.actor.ActorLogging import akka.actor.Address import akka.actor.Deploy import akka.actor.Props import akka.dispatch.Await import akka.pattern.ask import akka.remote.RemoteScope import akka.util.duration.intToDurationInt import akka.util.Timeout class LocalActor extends Actor with ActorLogging { //Get a reference to the remote actor val remoteActor = context.actorFor("akka://RemoteNodeApp@192.168.178.192:2552/user/remoteActor") implicit val timeout = Timeout(5 seconds) def receive: Receive = { case message: String => val future = (remoteActor ? message).mapTo[String] val result = Await.result(future, timeout.duration) log.info("Message received from Server -> {}", result) } }
LocalNodeApplication.scala
package org.akka.essentials.localnode import com.typesafe.config.ConfigFactory import akka.actor.ActorSystem import akka.actor.Props object LocalNodeApplication { def main(args: Array[String]): Unit = { // load the configuration val config = ConfigFactory.load().getConfig("LocalSys") val system = ActorSystem("LocalNodeApp", config) val clientActor = system.actorOf(Props[LocalActor]) clientActor ! "Hello" Thread.sleep(4000) system.shutdown() } }
运行结果如下(拖动图片或者另存为可以看大图)
local端和Remote端的代码见:https://github.com/hequn8128/akka/tree/master/AkkaRemotingExample
参考文献:
1.akka官方文档中文版:http://www.gtan.com/akka_doc/index.html
2.akka essential by Munish K.G
3.akka essential code:https://github.com/write2munish/Akka-Essentials/tree/master/AkkaRemotingExample
4.akka微内核:http://www.gtan.com/akka_doc/modules/microkernel.html#microkernel