作者:邵明东
Akka是一个用Scala编写的开源事件驱动中间件框架库,用于简化编写容错的、高可伸缩性的Java和Scala 的Actor 模型应用。用于构建高性能、高可靠以及分布式的Java和Scala应用程序,再加上Play2 等web应用框架以及大数据系统很容易形成功能强大的云计算服务。Akka由Typesafe Inc.发布维护,集成在反应式应用开发平台Typesafe Activator(Play2 framework+Scala+Akka)中。Akka已经成功运用在银行和电信等行业,系统几乎不宕机(高可用性99.9999999 %,一年只有 31ms宕机)。
基于Akka的反应式应用开发是一种新型的APP开发模式,在消费者与企业环境中越来越流行,与传统的web应用和移动应用的不同如下:
1. 事件驱动,很容易并行的异步的处理消息或事件。
2. 可伸缩,在节点内或者跨节点弹性的按需求调度计算资源。
3. 及时恢复,具有自动恢复和自动修复功能,提供不停顿的业务持续运营。
4. 敏捷反应,单页富用户界面极具吸引力,即时反馈用户的交互输入与其它激励输入。
Typesafe的反应式开发平台定位于快速开发复杂用户界面,在新的抽象层执行并发和并行任务,同时运用规模预测降低风险。Akka可以部署在云计算基础设施(I)、平台(P)和软件(S)的任意一层。
为此先理解云计算的服务形式:
1. IaaS(Infrastructure as a Service),基础设施即服务。消费者通过网络(LAN,WAN 或者Internet等)从完善的计算机基础设施获得服务,运算资源等,部署与执行操作系统或应用程式等各种软件。客户端无须购买服务器、软件等网络设备,即可任意部署和运行计算资源,不能管理或控制底层基础设施,但可以控制操作系统、储存装置、已部署的应用程序等,可以有限度地控制特定的网络元件,如主机端防火墙等。
2. SaaS(Softeware as a Service),软件即服务。它是一种软件交付模式,云端集中托管软件和相关数据,软件仅需通过互联网,不须安装即可使用。用户通常使用精简客户端经由一个网页浏览器来访问软件即服务。SaaS已经被吸纳进所有领先的企业级软件公司的战略中,最大的卖点之一就是通过将硬件和软件维护及支持外包给SaaS的提供者,来降低IT成本。
3. PaaS(Platform as a Service),平台即服务。它是基础平台或者开发环境作为一种服务提供的商业模式,以 SaaS 的形式提交给用户。PaaS 提供给企业定制研发的中间件平台,同时涵盖数据库和应用服务器等,提高Web平台上利用的资源数量,可以推进SaaS的发展。
事实上,云计算本身由基础设施(I)、平台(P)和软件(S)组成,I是系统基础,P是开发资源, S则是应用,如下图1所示:
因此云计算提供的服务有I,P和S的各种组合形成,IaaS,PaaS和SaaS之间的界限不是越来越模糊,而是越来越清晰,只是生产商可以提供的服务除了IaaS,PaaS和SaaS以外,还有I,P和S的组合形式I&PaaS,I&SaaS,P&SaaS和I&P&SaaS。统一起来就是XaaS,一切皆服务,“X as a service”、“anything as a service”或“everything as a service” 。有时XaaS被称为SPI模式(SaaS,PaaS,IaaS),其他例子还包括存储即服务(SaaS,storage as a service)、通信即服务(CaaS,communications as a service)、网络即服务(NaaS,network as a service)和监测即服务(MaaS,monitoring as a service)等等。
Akka是一种运用了舆论传播协议(gossip protocols)和自动故障检测的集群技术,运行在java虚拟机上,可以在异构系统之间部署集群运算,进一步扩展到网格计算。因此有人认为Akka是一种IaaS。同时Akka又是中间件,是PaaS的一个典型特征。Akka提供Java和Scala两套API,很容易开发应用程序,也能提供SaaS。Akka的Actor简化了多线程及其同步的操作,很容易编写云终端程序。
Actor模型由Carl Hewitt在上世纪70年代早期提出,是一种分布式编程中的并行和并发计算模型。Actor是一种程序上的抽象概念,被视为并行运算的基本单元:当一个Actor接收到一条消息,它可以做出一些决策、建立子Actor、传送或转发消息、决定要如何应答消息以及如何控制交互过程等等。其特点如下:
系统中的所有事物都可以抽象为一个Actor ,如同一个有生命特征的Class,可以继承Actor,创建子Actor ,响应外部激励(stimuli)等等
Actor封装了状态和行为操作,Actor之间完全独立,自主
不能直接访问Actor的内部状态,属性和方法,必须通过消息访问
消息传递是非阻塞和异步的,机制是邮件消息队列
Actor对不同消息采取的响应动作可以是并行的
事实上Actor模型是一个具有自适应和初步智能的软件智能体(Agent)模型,Actor集群则是软件多智能体(Multi-Agent)。将Actor的功能进一步扩充可形成适用于各种业务的自主,协同和学习的分布式多智能体系统。
Akka的ActorSystem生成的Actor具有以上Actor的特点,通过Actor的context.actorOf方法可以创建子Actor。Actor的receive方法响应消息,在case分支并行执行各种动作。Akka将底层机制(如线程、锁、非阻塞IO)隐藏,业务逻辑代码在Actor对象中,用这些代码发送和接受消息,并行执行动作,而同步、负载均衡、容错与伸缩则交由Akka处理。Akka 2.X改善了扩展性(每个Actor大约300Byte,每GB内存可创建数百万Actor),简化了终端(Endpoint)或数据中心环境下分布式应用程序的创建。Akka的其它特性包括:
1.位置透明。Akka使用Actor路径来实现位置透明性。一个Actor在Akka系统节点中的位置表示为
akka.<protocol>://<actor system>@<hostname>:<port>/<actor path>
<protocol>是通信协议(如tcp和udp)。<actor system>是Actor系统的名字(传递给ActorSystem的Actor系统名字符串)。<hostname>是Actor系统所在的主机名,也可以是IP字符串。<port>是Actor系统的端口。<actor path>是Actor系统的Actor路径,ActorSystem创建的Actor位于/user。在一台IP为192.168.0.2的主机,端口为2552上用名子为actorSystemName的ActorSystem创建的一个名子为actorName的Akka Actor可表示为
akka.tcp://[email protected]:2552/user/actorName
2.基于配置的部署,在运行时指定拓扑。配置文件默认为reference.conf,对于Akka应用程序它位于工程的classpath根目录(如/bin)。reference.conf的一个例子如下
akka {
actor {
provider = "akka.remote.RemoteActorRefProvider"
}
remote {
enabled-transports = ["akka.remote.netty.tcp"]
netty.tcp {
hostname = "192.168.0.16"
port = 5150
}
}
}
对于remote Actor的配置一般仅需修改netty.tcp 中的hostname和port。
3.监督与监控,监控每一个Akka组件的错误或终止。Akka实现的是“父监管”,顶部的Actor由Akka提供,每一个子Actor都由它的父Actor监管。这种限制使得actor的树形层次有明确的形式。
4.消息路由。Actor发送的消息可以经过一个路由Actor或者软路由器转发至另一个Actor。
用一个Akka remote Actor的例子说明开发过程。一共4个工程项目:dataType(定义的数据类型),akkaLocal(本地Actor系统,包括一个服务Actor,负责与用户Actor交互,是控制节点),akkaRemote(远程Actor系统,负责计算任务,是计算节点),akkaUser(用户APP Actor,,是客户端)。开发工具为Eclipse(Winows版本,eclipse-jee-kepler-SR2-win32-x86_64.zip。Linux版本,eclipse-jee-kepler-SR2-linux-gtk-x86_64.tar.gz),Scala-IDE插件(Eclipse 4.3-scala2.11.1-update-site.zip)。开发语言为scala-2.11.1(Windows和Linux版本)。Akka为2.3.4版本(Windows和Linux版本)。本地操作系统为Windows 8.1中文,在本地系统用VirtualBox安装一个Kubuntu14.04,akkaLocal和akkaUser运行在Windows 8.1上,akkaRemote运行在Kubuntu14.04上。
Windows系统配置如下:
处理器:Inter Core i7-4702MQ [email protected],4核
内存:8G
系统类型:64位Windows 8.1
Linux系统配置如下:
处理器:VirtualBox虚拟CPU,1核
内存:2G
系统类型:64位Kubuntu14.04桌面版
网络:
300Mbps无线网,VirtualBox桥接网卡
Windows IP:192.168.0.2,Kubuntu IP:192.168.0.16
认为读者熟练使用Eclipse及其插件,Scala-2.11.1 和Akka-2.3.4已安装好(Windows 8.1和Kubuntu14.04),在Eclipse中新建Scala-2.11.1库(scala2.11.1,导入Scala安装目录中lib的所有包)和Akka-2.3.4库(akka_2.11-2.3.4,导入Akka安装目录中lib/akka的所有包)。如下图2所示:
在Windows 系统下,Eclipse中创建Scala工程dataType定义消息数据类型,在src下创建dataType包,添加Scala-2.11.1库,在dataType包中新建Scala Class,源文件为MsgData.scala,修改代码如下:
package dataType
class MsgData(var msg:String) {
def this()
{
this("Message")
}
}
case object Start
case class Message(msg: String)
case class MessageInt(a:Int,b:Int)
object Demo extends App {
println("This is a message data library package:")
println("class MsgData(var msg:String)")
println("case object Start")
println("case class Message(msg: String)")
println("case class MessageInt(a:Int,b:Int)")
}
这些Class和Object定义了一些消息,工程中仅使用了 MessageInt,它定义了一个有两个整数运算的消息。
在工程的根目录新建MANIFEST.MF文件,代码如下:
Manifest-Version: 1.0
Class-Path: scala-actors-2.11.0.jar 空格
空格 scala-actors-migration_2.11-1.1.0.jar 空格
空格 scala-compiler.jar 空格
空格 scala-continuations-library_2.11-1.0.2.jar 空格
空格 scala-continuations-plugin_2.11.1-1.0.2.jar 空格
空格 scala-library.jar 空格
空格 scala-parser-combinators_2.11-1.0.1.jar 空格
空格 scala-reflect.jar 空格
空格 scala-stm_2.11-0.7.jar 空格
空格 scala-swing_2.11-1.0.1.jar 空格
空格 scala-xml_2.11-1.0.2.jar 空格
空格 slf4j-api-1.7.5.jar 空格
空格 uncommons-maths-1.2.2a.jar 空格
Main-Class: dataType.Demo
这个文件用来将Class文件打包成jar文件,注意Class-Path的XXXXX.jar前后必须有空格分隔每一个包。dataType工程MANIFEST.MF中Class-Path下是Scala-2.11.1库的包。然后使用Eclipse的打包工具,选择清单MANIFEST.MF将dataType导出为库文件datatype.jar。将库文件datatype.jar存放在一个目录(例如D:\program\scala\prjLib,本例是在Scala的安装目录下)。新建库PrjLibrary,导入D:\program\scala\prjLib\datatype.jar,如图2所示。然后这个库PrjLibrary就可以添加到另外3个工程,统一消息数据类型。dataType工程如下图3所示:
在Kubuntu系统下,Eclipse中创建Scala工程akkaRemote,用于接收和执行akkaLocal发送的计算任务消息命令,在src下创建remote包,添加PrjLibrary库,Scala-2.11.1库和Akka-2.3.4库。在remote包中新建Scala Application,源文件为HelloRemote.scala,代码如下:
package remote
import akka.actor._
import akka.remote._
import dataType._
class RemoteActor extends Actor {
def receive = {
case msg: String => {
println(s"RemoteActor received message '$msg'")
//sender ! "k"
}
case MessageInt(a,b) => {
println(" RemoteActor got MesageInt:"+a+"*"+b)
sender ! ( a*b)
}
case _ =>
println(" RemoteActor got something unexpected.")
}
}
object HelloRemote extends App {
val system = ActorSystem("HelloRemoteSystem")
val remoteActor = system.actorOf(Props[RemoteActor], name = "RemoteActor")
remoteActor ! "The RemoteActor is alive"
}
receive方法接收到一个MessageInt(a,b) 消息后,计算a*b,将结果回发给sender(akkaLocal中的LocalActor)。
在src目录中新建Akka的配置文件application.conf,代码如下:
akka {
//loglevel = "DEBUG"
actor {
provider = "akka.remote.RemoteActorRefProvider"
}
remote {
enabled-transports = ["akka.remote.netty.tcp"]
transport = "akka.remote.netty.NettyRemoteTransport"
//log-sent-messages = on
//log-received-messages = on
netty.tcp {
hostname = "192.168.0.16"
port = 5150
}
}
}
在工程的根目录新建MANIFEST.MF文件,代码如下:
Manifest-Version: 1.0
Class-Path: lib/akka-actor_2.11-2.3.4.jar
lib/akka-agent_2.11-2.3.4.jar
lib/akka-camel_2.11-2.3.4.jar
lib/akka-cluster_2.11-2.3.4.jar
lib/akka-contrib_2.11-2.3.4.jar
lib/akka-dataflow_2.11-2.3.4.jar
lib/akka-durable-mailboxes-2.3.4.jar
lib/akka-file-mailbox_2.11-2.3.4.jar
lib/akka-kernel_2.11-2.3.4.jar
lib/lib/akka-mailboxes-common_2.11-2.3.4.jar
lib/akka-multi-node-testkit_2.11-2.3.4.jar
lib/akka-persistence-experimental_2.11-2.3.4.jar
lib/akka-remote_2.11-2.3.4.jar
lib/akka-remote-tests_2.11-2.3.4.jar
lib/akka-slf4j_2.11-2.3.4.jar
lib/akka-testkit_2.11-2.3.4.jar
lib/akka-transactor_2.11-2.3.4.jar
lib/camel-core-2.10.3.jar
lib/config-1.2.1.jar
lib/guava-12.0.jar
lib/hawtjni-runtime-1.8.jar
lib/jline-2.11.jar
lib/jsr305-1.3.9.jar
lib/leveldb-0.5.jar
lib/leveldb-api-0.5.jar
lib/leveldbjni-1.7.jar
lib/leveldbjni-all-1.7.jar
lib/leveldbjni-linux32-1.5.jar
lib/leveldbjni-linux64-1.5.jar
lib/leveldbjni-osx-1.5.jar
lib/leveldbjni-win32-1.5.jar
lib/leveldbjni-win64-1.5.jar
lib/netty-3.8.0.Final.jar
lib/protobuf-java-2.5.0.jar
lib/scala-actors-2.11.0.jar
lib/scala-actors-migration_2.11-1.1.0.jar
lib/scala-compiler.jar
lib/scala-continuations-library_2.11-1.0.2.jar
lib/scala-continuations-plugin_2.11.1-1.0.2.jar
lib/scala-library.jar
lib/scala-parser-combinators_2.11-1.0.1.jar
lib/scala-reflect.jar
lib/scala-stm_2.11-0.7.jar
lib/scala-swing_2.11-1.0.1.jar
lib/scala-xml_2.11-1.0.2.jar
lib/slf4j-api-1.7.5.jar
lib/uncommons-maths-1.2.2a.jar
lib/datatype.jar
Main-Class: remote.HelloRemote
同dataType工程中的MANIFEST.MF文件注意空格。本例将Scala和Akka的所有库文件都添加到了Class-Path中,可以只添加源程序导入包的jar文件。
akkaRemote工程如下图4所示:
如果出现无法绑定到akkaRemote计算节点的错误,可以在远程计算节点主机上运行命令sudo fuser -k -n tcp 5150,然后再重新运行akkaRemote。
在Windows系统下,Eclipse中创建Scala工程akkaLocal,用于接收和执行akkaUser 请求的计算服务消息命令,在src下创建local包,添加PrjLibrary库,Scala-2.11.1库和Akka-2.3.4库。在local包中新建Scala Application,源文件为Local.scala,代码如下
package local
import akka.actor._
import akka.remote._
import dataType._
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
val remote = context.actorSelection("akka.tcp://[email protected]:5150/user/RemoteActor")
var svr = context.actorOf(Props[ServerActor], name = "server")
context.watch(svr)
def receive = {
case "START" => {
println("LocalActor received START")
remote ! "Hello from the LocalActor"
}
case msg:String => {
//sender ! "a"
println(s"LocalActor received message: '$msg'")
}
case MessageInt(a,b) => {
println("Received task from user:"+MessageInt(a,b).toString())
remote ! MessageInt(a,b)
}
case resultInt:Int => {
svr ! resultInt
}
case _ =>
println("LocalActor got something unexpected.")
}
}
class ServerActor extends Actor {
var localAct = context.actorSelection("akka://LocalSystem/user/LocalActor")
var user1 = context.actorSelection("akka://LocalSystem/user/LocalActor")
def receive = {
case "START" => {
println("ServerActor received START")
}
case MessageInt(a,b) => {
localAct ! MessageInt(a,b)
user1=context.actorSelection(sender.path.toString())
println("ServerActor user1 path:"+sender.path.toString())
}
case resultInt:Int => {
user1 ! resultInt
}
case _ =>
println("LocalActor got something unexpected.")
}
}
LocalActor的receive方法接收到一个MessageInt(a,b) 消息后,将消息分发给remote
(RemoteActor),remote计算a*b后将结果发回,LocalActor的receive方法接收到结果后,再将结果发给子Actor svr(ServerActor)。 ServerActor的receive方法接收到一个MessageInt(a,b) 消息后,将任务发给 localAct(LocalActor)执行, LocalActor将结果发回, ServerActor接收为消息 resultInt,然后发送给用户 user1(AppActor)。
在src目录中新建Akka的配置文件application.conf,代码如下:
akka {
//loglevel = "DEBUG"
actor {
provider = "akka.remote.RemoteActorRefProvider"
}
remote {
enabled-transports = ["akka.remote.netty.tcp"]
transport = "akka.remote.netty.NettyRemoteTransport"
//log-sent-messages = on
//log-received-messages = on
netty.tcp {
hostname = "192.168.0.2"
port = 2562
}
}
}
在工程的根目录新建MANIFEST.MF文件,代码如下(注意空格):
Manifest-Version: 1.0
Class-Path: lib/akka-actor_2.11-2.3.4.jar
lib/akka-agent_2.11-2.3.4.jar
lib/akka-camel_2.11-2.3.4.jar
lib/akka-cluster_2.11-2.3.4.jar
lib/akka-contrib_2.11-2.3.4.jar
lib/akka-dataflow_2.11-2.3.4.jar
lib/akka-durable-mailboxes-2.3.4.jar
lib/akka-file-mailbox_2.11-2.3.4.jar
lib/akka-kernel_2.11-2.3.4.jar
lib/lib/akka-mailboxes-common_2.11-2.3.4.jar
lib/akka-multi-node-testkit_2.11-2.3.4.jar
lib/akka-persistence-experimental_2.11-2.3.4.jar
lib/akka-remote_2.11-2.3.4.jar
lib/akka-remote-tests_2.11-2.3.4.jar
lib/akka-slf4j_2.11-2.3.4.jar
lib/akka-testkit_2.11-2.3.4.jar
lib/akka-transactor_2.11-2.3.4.jar
lib/camel-core-2.10.3.jar
lib/config-1.2.1.jar
lib/guava-12.0.jar
lib/hawtjni-runtime-1.8.jar
lib/jline-2.11.jar
lib/jsr305-1.3.9.jar
lib/leveldb-0.5.jar
lib/leveldb-api-0.5.jar
lib/leveldbjni-1.7.jar
lib/leveldbjni-all-1.7.jar
lib/leveldbjni-linux32-1.5.jar
lib/leveldbjni-linux64-1.5.jar
lib/leveldbjni-osx-1.5.jar
lib/leveldbjni-win32-1.5.jar
lib/leveldbjni-win64-1.5.jar
lib/netty-3.8.0.Final.jar
lib/protobuf-java-2.5.0.jar
lib/scala-actors-2.11.0.jar
lib/scala-actors-migration_2.11-1.1.0.jar
lib/scala-compiler.jar
lib/scala-continuations-library_2.11-1.0.2.jar
lib/scala-continuations-plugin_2.11.1-1.0.2.jar
lib/scala-library.jar
lib/scala-parser-combinators_2.11-1.0.1.jar
lib/scala-reflect.jar
lib/scala-stm_2.11-0.7.jar
lib/scala-swing_2.11-1.0.1.jar
lib/scala-xml_2.11-1.0.2.jar
lib/slf4j-api-1.7.5.jar
lib/uncommons-maths-1.2.2a.jar
lib/datatype.jar
Main-Class: local.Local
akkaLocal工程如下图5所示:
为便于演示将akkaLocal工程的二进制文件打包成akkaLocal.jar文件,放入一个文件夹(例如jars),在该文件夹里新建lib目录将所有PrjLibrary库,Scala-2.11.1库和Akka-2.3.4库的jar文件复制进去。在Windows cmd窗口下进入akkaLocal.jar文件的目录运行java -jar akkaLocal.jar可启动服务。
在Windows系统下,Eclipse中创建Scala工程akkaUser,用作客户端向akkaLocal发送用户请求的计算服务消息执行命令,在src下创建akkauser包,添加PrjLibrary库,Scala-2.11.1库和Akka-2.3.4库。在akkauser包中新建Scala Application,源文件AkkaUser.scala,代码如下:
package akkauser
import akka.actor._
import akka.remote._
import dataType._
object AkkaUser extends App {
implicit val system = ActorSystem("AppUserSystem")
val appActor = system.actorOf(Props[AppActor], name = "AppUserActor") // the local actor
appActor ! "START"
}
class AppActor extends Actor {
var server = context.actorSelection("akka.tcp://[email protected]:2562/user/LocalActor/server")
var x=0
def receive = {
case "START" => {
println("AppActor received START")
server ! MessageInt(1,1)
}
case rst:Int => {
println("result from server:"+rst)
x+=1
if(x>10) x=0
server ! MessageInt(2,x)
}
}
}
AppActor收到一个"START"启动命令后,向 LocalActor的子Actor server发送一个1*1的请求,AppActor收到1*1的结果rst 后打印出结果,变量x计数(0~10),再发送一个2*x的请求,如此循环计算2*(0,1,~10)=0,2,~20。
在src目录中新建Akka的配置文件application.conf,代码如下:
akka {
//loglevel = "DEBUG"
actor {
provider = "akka.remote.RemoteActorRefProvider"
}
remote {
enabled-transports = ["akka.remote.netty.tcp"]
transport = "akka.remote.netty.NettyRemoteTransport"
//log-sent-messages = on
//log-received-messages = on
netty.tcp {
hostname = "192.168.0.2"
port = 15601
}
}
}
在工程的根目录新建MANIFEST.MF文件,代码如下(注意空格):
Manifest-Version: 1.0
Class-Path: lib/akka-actor_2.11-2.3.4.jar
lib/akka-agent_2.11-2.3.4.jar
lib/akka-camel_2.11-2.3.4.jar
lib/akka-cluster_2.11-2.3.4.jar
lib/akka-contrib_2.11-2.3.4.jar
lib/akka-dataflow_2.11-2.3.4.jar
lib/akka-durable-mailboxes-2.3.4.jar
lib/akka-file-mailbox_2.11-2.3.4.jar
lib/akka-kernel_2.11-2.3.4.jar
lib/lib/akka-mailboxes-common_2.11-2.3.4.jar
lib/akka-multi-node-testkit_2.11-2.3.4.jar
lib/akka-persistence-experimental_2.11-2.3.4.jar
lib/akka-remote_2.11-2.3.4.jar
lib/akka-remote-tests_2.11-2.3.4.jar
lib/akka-slf4j_2.11-2.3.4.jar
lib/akka-testkit_2.11-2.3.4.jar
lib/akka-transactor_2.11-2.3.4.jar
lib/camel-core-2.10.3.jar
lib/config-1.2.1.jar
lib/guava-12.0.jar
lib/hawtjni-runtime-1.8.jar
lib/jline-2.11.jar
lib/jsr305-1.3.9.jar
lib/leveldb-0.5.jar
lib/leveldb-api-0.5.jar
lib/leveldbjni-1.7.jar
lib/leveldbjni-all-1.7.jar
lib/leveldbjni-linux32-1.5.jar
lib/leveldbjni-linux64-1.5.jar
lib/leveldbjni-osx-1.5.jar
lib/leveldbjni-win32-1.5.jar
lib/leveldbjni-win64-1.5.jar
lib/netty-3.8.0.Final.jar
lib/protobuf-java-2.5.0.jar
lib/scala-actors-2.11.0.jar
lib/scala-actors-migration_2.11-1.1.0.jar
lib/scala-compiler.jar
lib/scala-continuations-library_2.11-1.0.2.jar
lib/scala-continuations-plugin_2.11.1-1.0.2.jar
lib/scala-library.jar
lib/scala-parser-combinators_2.11-1.0.1.jar
lib/scala-reflect.jar
lib/scala-stm_2.11-0.7.jar
lib/scala-swing_2.11-1.0.1.jar
lib/scala-xml_2.11-1.0.2.jar
lib/slf4j-api-1.7.5.jar
lib/uncommons-maths-1.2.2a.jar
lib/datatype.jar
Main-Class: akkauser.AkkaUser
akkaUser工程如下图6所示:
所有工程已创建好,可以开始运行,首先在Kubuntu下的Eclipse中run akkaRemote,然后在Windows的cmd中运行akkaLocal.jar,最后在Windows下的Eclipse中run akkaUser。 akkaRemote的运行如下图7所示:
akkaLocal.jar的运行如下图8所示:
akkaUser 的运行如下图9所示:
此时的Windows系统网络资源如下图10所示:
Windows系统CPU资源如下图11所示:
Kubuntu系统资源如下图12所示:
以上是在计算一个乘法操作情况下的系统资源,占用的网络带宽在500~600Kps,如果计算一个加法操作占用的网络带宽在1.5~1.6Mps,如果仅发送一个字节的字符串占用的网络带宽在6Mps左右。
本例仅仅使用了Akka的远程Actor就可以构建一个简单的云计算模型,具有本地服务节点,远程计算节点和客户端的功能,如果再运用Akka的集群管理功能和Play2 web框架就可以构建功能强大的云计算应用。