zoukankan      html  css  js  c++  java
  • akka构建简单分布式应用

    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


  • 相关阅读:
    消息队列 ActiveMQ
    Redis
    SQL 怎么用EXISTS替代IN
    SQL优化
    为什么要重写hashCode()和equals()方法
    Redis的介绍和面试可能问到的问题
    建立私有CA和颁发证书
    修复grub2
    Centos 7 进入救援模式
    Centos 服务的常用命令
  • 原文地址:https://www.cnblogs.com/bluejoe/p/5115842.html
Copyright © 2011-2022 走看看