SBT构建Akka项目

学习Akka项目断断续续弄了好久,今天刚好把SBT装好,顺便也将之前遗留的Akka Demo的问题解决掉了,跟大家分享一下~

1.准备工作

(1)安装Akka,到Akka官网下载一个安装包就可以了,地址: http://akka.io/downloads/?_ga=1.235296577.1332829892.1429753844

(2)安装STB,地址:http://www.scala-sbt.org/download.html

   需要注意的两点:

   a. 在需要创建工程的目录下,如E:\SBT,编写文件sbt.bat,内容如下:

      set SCRIPT_DIR=%~dp0
       java %SBT_OPTS% -Xms512M -Xmx512M -Xss1M -XX:+CMSClassUnloadingEnabled -XX:MaxPermSize=256M -jar "%SCRIPT_DIR%sbt-launch.jar" %*

    b. 安装完后,可以在sbt的bin目录下找到sbt-launch.jar,与sbt.bat放在同一目录下

    c.点击sbt.bat,就可以运行sbt了,这个过程中需要很长时间下载一些依赖包,比较麻烦。下载完后进入cmd下,执行sbt命令查看安装是否成功。

(3) 下载scala,地址:http://www.scala-lang.org/download/

     注意,用Scala开发Akka项目时,两者的版本号要对应起来,否则很容易报错。笔者用的scala版本是2.11.5,Akka版本是2.3.11


2. 创建Akka工程

   准备工作做好了之后,就可以创建Akka工程了。将两个例子,一个是计算圆周率的Pi(参考http://www.gtan.com/akka_doc/intro/getting-started-first-scala.html),另一个是

   Akka Remote(参考http://alvinalexander.com/scala/simple-akka-actors-remote-example )

   2.1 运用Akka实现Pi的近似计算

   (1)在目录E:\SBT下创建工程目录 ,如PiProject ,然后按照下面的示意图创建目录和文件

HelloRemote/
|-- build.sbt
|-- src
    |-- main
    │   +-- scala
    │       +-- Pi.scala
 
   
其中,Pi.scala的内容如下:

/**
 * Copyright (C) 2009-2012 Typesafe Inc. <http://www.typesafe.com>
 */ 
import akka.actor._
import akka.routing.RoundRobinRouter
//import akka.util.Duration
//import akka.util.duration._
import scala.concurrent.duration._

object Pi {
  def main(args:Array[String]){
    calculate(4, 10000, 10000)
    
  }
  
//  calculate(nrOfWorkers = 4, nrOfElements = 10000, nrOfMessages = 10000)
 
  sealed trait PiMessage
  case object Calculate extends PiMessage
  case class Work(start: Int, nrOfElements: Int) extends PiMessage
  case class Result(value: Double) extends PiMessage
  case class PiApproximation(pi: Double, duration: Duration)
 
  class Worker extends Actor {
 
    def calculatePiFor(start: Int, nrOfElements: Int): Double = {
      var acc = 0.0
      for (i ← start until (start + nrOfElements))
        acc += 4.0 * (1 - (i % 2) * 2) / (2 * i + 1)
      acc
    }
 
    def receive = {
      case Work(start, nrOfElements) =>
        sender ! Result(calculatePiFor(start, nrOfElements)) // perform the work
    }
  }
 
  class Master(nrOfWorkers: Int, nrOfMessages: Int, nrOfElements: Int, listener: ActorRef)
    extends Actor {
 
    var pi: Double = _
    var nrOfResults: Int = _
    val start: Long = System.currentTimeMillis
 
    val workerRouter = context.actorOf(
      Props[Worker].withRouter(RoundRobinRouter(nrOfWorkers)), name = "workerRouter")
 
    def receive = {
      case Calculate =>
        for (i ← 0 until nrOfMessages) workerRouter ! Work(i * nrOfElements, nrOfElements)
      case Result(value) =>
        pi += value
        nrOfResults += 1
        if (nrOfResults == nrOfMessages) {
          // Send the result to the listener
          listener ! PiApproximation(pi, duration = (System.currentTimeMillis - start).millis)
          // Stops this actor and all its supervised children
          context.stop(self)
        }
    }
 
  }
 
  class Listener extends Actor {
    def receive = {
      case PiApproximation(pi, duration) =>
        println("\n\tPi approximation: \t\t%s\n\tCalculation time: \t%s"
          .format(pi, duration))
        context.system.shutdown()
    }
  }
 
 
  def calculate(nrOfWorkers: Int, nrOfElements: Int, nrOfMessages: Int) {
    // Create an Akka system
    val system = ActorSystem("PiSystem")
 
    // create the result listener, which will print the result and shutdown the system
    val listener = system.actorOf(Props[Listener], name = "listener")
 
    // create the master
    val master = system.actorOf(Props(new Master(
      nrOfWorkers, nrOfMessages, nrOfElements, listener)),
      name = "master")
 
    // start the calculation
    master ! Calculate
 
  }
  
 
}

说明:Akka2.0官方中文版(http://www.gtan.com/akka_doc/intro/getting-started-first-scala.html)中计算Pi的例子缺少了 main()函数,以及依赖包duration与此示例也有所不同。

(2)运行

    在cmd下进入工程目录 E:\SBT\PiProject,执行 sbt run 命令,就可以得到计算结果:

    


 2.2 运用STB构建Akka Remote项目

      第一个示例Pi是本地实现Akka的过程,此处给出实现远程Akka Remote的例子,参考http://alvinalexander.com/scala/simple-akka-actors-remote-example

   (1) Remote工程,创建工程目录 E:\SBT\HelloRemote,然后按照如下示意图创建目录和文件

  

HelloRemote/
|-- build.sbt
|-- src
    |-- main
    │   |-- java
    │   |-- resources
    │   │   +-- application.conf
    │   +-- scala
    │       +-- remote
    │           +-- HelloRemote.scala
    +-- test
        |-- java
        |-- resources
        +-- scala

其中,build.sbt 内容如下:

name := "HelloRemote"

version := "1.0"

scalaVersion := "2.11.5"

resolvers += "Typesafe Repository" at "http://repo.typesafe.com/typesafe/releases/"

libraryDependencies ++= Seq(
  "com.typesafe.akka" %% "akka-actor" % "2.3.11",
  "com.typesafe.akka" %% "akka-remote" % "2.3.11"
)

其中,配置文件application.conf 内容如下,此例Akka的版本号为2.3, Akka2.1的版本略有不同:

# akka 2.3

akka {
  loglevel = "INFO"
  actor {
    provider = "akka.remote.RemoteActorRefProvider"
  }
  remote {
    enabled-transports = ["akka.remote.netty.tcp"]
    netty.tcp {
      hostname = "127.0.0.1"
      port = 5150
    }
    log-sent-messages = on
    log-received-messages = on
  }
}

HelloRemote.scala内容如下:

package remote

import akka.actor._

object HelloRemote extends App  {
  val system = ActorSystem("HelloRemoteSystem")
  val remoteActor = system.actorOf(Props[RemoteActor], name = "RemoteActor")
  remoteActor ! "The RemoteActor is alive"
}

class RemoteActor extends Actor {
  def receive = {
    case msg: String =>
        println(s"RemoteActor received message '$msg'")
        sender ! "Hello from the RemoteActor"
  }
}


  (2) Local工程,Local工程的内容和过程与Remote大部分都很相似

      首先创建目录,E:\SBT\HelloLocal,然后创建其他内容:

HelloLocal/
|-- build.sbt
|-- src
    |-- main
    │   |-- java
    │   |-- resources
    │   │   +-- application.conf
    │   +-- scala
    │       +-- local
    │           +-- Local.scala
    +-- test
        |-- java
        |-- resources
        +-- scala

其中build.sbt内容与Remote一样,application.config

# akka 2.3


akka {
  loglevel = "INFO"


  actor {
    provider = "akka.remote.RemoteActorRefProvider"
  }


  remote {
    enabled-transports = ["akka.remote.netty.tcp"]
    netty.tcp {
      hostname = "127.0.0.1"
      port = 0
    }


    log-sent-messages = on
    log-received-messages = on
  }


}

  HelloLocal.scala内容如下:

package local

import akka.actor._

object Local extends App {

  implicit val system = ActorSystem("LocalSystem")
  val localActor = system.actorOf(Props[LocalActor], name = "LocalActor")  // the local actor
  localActor ! "START"                                                     // start the action

}

class LocalActor extends Actor {

  // create the remote actor (Akka 2.3 syntax)
  val remote = context.actorFor("akka.tcp://HelloRemoteSystem@127.0.0.1:5150/user/RemoteActor")
  var counter = 0

  def receive = {
    case "START" =>
        remote ! "Hello from the LocalActor"
    case msg: String =>
        println(s"LocalActor received message: '$msg'")
        if (counter < 5) {
            sender ! "Hello back to you"
            counter += 1
        }
  }
}

(3)运行

   先运行Remote,cd 进入HelloRemote目录,键入sbt run命令,开启remote actor system

  然后在一个新的cmd窗口进入 HellLocal目录,键入sbt run命令,开启local actor system

  运行结果如下:

 remote:


local:


 大工告成!




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值