所谓的Aggregate模式,其实就是聚合模式,跟masterWorker模式有点类似,但其出发点不同。masterWorker模式是指master向worker发送命令,worker完成某种业务逻辑。而聚合模式则刚好相反,由各个worker完成某种业务逻辑后,把结果汇总发给某个actor,这个actor不一定是masterActor。

class AggregateMasterActor extends Actor{
override def receive: Receive = {
case cmd: AggregateCommand.Aggregate =>
// 将此次汇总结果汇报给from,为了简化,此处用self替代
val from = self
val backendActor = context.actorOf(Props(new AggregateMasterBackendActor(from,cmd.parallel)),s"AggregateMasterBackendActor-${cmd.at}")
backendActor ! cmd
case AggregateBackendEvent.WorkDone(sum) =>
val from = sender()
println(s"AggregateMasterActor [${self.path.name}] 收到 ${from.path.name} 汇总结果 $sum")
}
}
class AggregateMasterBackendActor(replyTo:ActorRef,parallel:Int) extends Actor{
var counter = 0
var sum = 0L
override def receive: Receive = {
case AggregateCommand.Aggregate(_) =>
println(s"AggregateMasterBackendActor [${self.path.name}] 开始工作,parallel $parallel,工作结果汇总给 ${replyTo.path.name}")
1 to parallel foreach { i =>
val worker = context.actorOf(Props(new AggregateWorker(self)),s"AggregateWorker-$i")
worker ! AggregateBackendCommand.Aggregate(i,parallel)
}
case AggregateWorkerEvent.WorkDone(result) =>
counter += 1
sum += result
if(counter == parallel){
replyTo ! AggregateBackendEvent.WorkDone(sum)
context.stop(self)
println(s"AggregateMasterBackendActor [${self.path.name}] 工作结束退出")
}
}
}
class AggregateWorker(replyTo:ActorRef) extends Actor{
def calcResult(index:Int,parallel:Int):Long = index * parallel
override def receive: Receive = {
case AggregateBackendCommand.Aggregate(index,parallel) =>
println(s"AggregateWorker [${self.path.name}] 开始工作 index=$index,工作汇总给 ${replyTo.path.name}")
val result = calcResult(index,parallel)
replyTo ! AggregateWorkerEvent.WorkDone(result)
println(s"AggregateWorker [${self.path.name}] 工作结束退出")
context.stop(self)
}
} object AggregatePattern {
def main(args: Array[String]): Unit = {
val system = ActorSystem("AggregatePattern",ConfigFactory.load())
val aggregateMasterActor = system.actorOf(Props(new AggregateMasterActor),"AggregateMasterActor")
aggregateMasterActor ! AggregateCommand.Aggregate(3)
}
}

输出:

AggregateMasterBackendActor [AggregateMasterBackendActor-1531383454073] 开始工作,parallel 3,工作结果汇总给 AggregateMasterActor
AggregateWorker [AggregateWorker-1] 开始工作 index=1,工作汇总给 AggregateMasterBackendActor-1531383454073
AggregateWorker [AggregateWorker-2] 开始工作 index=2,工作汇总给 AggregateMasterBackendActor-1531383454073
AggregateWorker [AggregateWorker-3] 开始工作 index=3,工作汇总给 AggregateMasterBackendActor-1531383454073
AggregateWorker [AggregateWorker-1] 工作结束退出
AggregateWorker [AggregateWorker-3] 工作结束退出
AggregateWorker [AggregateWorker-2] 工作结束退出
AggregateMasterBackendActor [AggregateMasterBackendActor-1531383454073] 工作结束退出
AggregateMasterActor [AggregateMasterActor] 收到 AggregateMasterBackendActor-1531383454073 汇总结果 18

  从代码来看该设计模式也比较简单,就是由Master创建以临时的子actor,此处命名为MasterBackend,将汇报对象的actorRef以构造函数的形式传递给MasterBackend,此处为了简单用self替代;MasterBackend根据并行参数,创建对应个数的workerActor,并把本身的actorRef以构造函数的形式传递给workerActor,workerActor执行具体的业务逻辑,并将汇总结果,发送给replyTo(也就是MasterBackend);MasterBackend收到workerActor的汇总结果,根据并行参数,判断所有子actor是否执行结束,若执行结束,此次计算完成,将汇总后的结果,发送给replyTo(也就是MasterActor)。

  上面这种设计模式有一个明显的好处,就是Master可以迅速创建大量的聚合工作而不阻塞,因为它收到命令后,只是简单的创建MasterBackend,工作交给它去执行,这个过程非常快。如果某个聚合工作比较慢,并不会影响其他任务。

  之所以说这个设计模式非常重要,是因为在spark/storm等大多分布式框架中都有它的影子。他们都选择将功能进行拆解,专门的节点或actor分别负责任务的接收、创建、执行、汇总这些工作,工作之间互不影响。如果能够深刻的理解这种设计模式,你将会设计出一个架构分层合理、互相解耦的高质量应用系统。

akka设计模式系列-Aggregate模式的更多相关文章

  1. akka设计模式系列-Backend模式

    上一节我们介绍了Akka使用的基本模式,简单点来说就是,发消息给actor,处理结束后返回消息.但这种模式有个缺陷,就是一旦某个消息处理的比较慢,就会阻塞后面所有消息的处理.那么有没有方法规避这种阻塞 ...

  2. akka设计模式系列-While模式

    While模式严格来说是while循环在Akka中的合理实现.while是开发过程中经常用到的语句之一,也是绝大部分编程语言都支持的语法.但while语句是一个循环,如果循环条件没有达到会一直执行wh ...

  3. akka设计模式系列-Chain模式

    链式调用在很多框架和系统中经常存在,算不得上是我自己总结的设计模式,此处只是简单介绍在Akka中的两种实现方式.我在这边博客中简化了链式调用的场景,简化后也更符合Akka的设计哲学. trait Ch ...

  4. akka设计模式系列-基础模式

    本文介绍akka的基本使用方法,由于属于基础功能,想不出一个很高大上的名称,此处就以基础模式命名.下文会介绍actor的使用方法,及其优劣点. class SimpleActor(name:Strin ...

  5. akka设计模式系列-慎用ask

    慎用ask应该是Akka设计的一个准则,很多时候我们应该禁用ask.之所以单独把ask拎出来作为一篇博文,主要是akka的初学者往往对ask的使用比较疑惑. "Using ask will ...

  6. akka设计模式系列-消息模型(续)

    在之前的akka设计模式系列-消息模型中,我们介绍了akka的消息设计方案,但随着实践的深入,发现了一些问题,这里重新梳理一下设计方法,避免之前的错误.不当的观点给大家带来误解. 命令和事件 我们仍然 ...

  7. akka设计模式系列

    由于本人爱好Scala,顺便也就爱好Akka,但目前网上对Akka的介绍大多都是概念上或技术方向上的介绍,基本没有Akka设计模式或者Actor模型设计模式的资料.这对于Akka的普及非常不利,因为即 ...

  8. PHP设计模式系列 - 外观模式

    外观模式 通过在必需的逻辑和方法的集合前创建简单的外观接口,外观设计模式隐藏了调用对象的复杂性. 外观设计模式和建造者模式非常相似,建造者模式一般是简化对象的调用的复杂性,外观模式一般是简化含有很多逻 ...

  9. akka设计模式系列-actor锚定

    actor锚定模式是指使用actorSelection对acor进行锚定的设计模式,也可以说是一个对actor的引用技巧.在某些情况下,我们可能需要能够根据Actor的path锚定对应的实例.简单来说 ...

随机推荐

  1. linux内核开发程序风格

    变量命名法 这里是linux不是windows,所以匈牙利命名法是不允许使用的,在内核中,局部变量只要可以明确表达自己的意思,可以使用idx,i这种名字的id, 全局函数和变量需要有表达性的名字例如g ...

  2. kata练习题

    This time no story, no theory. The examples below show you how to write function accum: Examples: ac ...

  3. python之cookbook-day01

    第一章:数据结构和算法 1.1 解压序列赋值给多个变量 >>> p = (4, 5) >>> x, y = p >>> x 4 >>& ...

  4. How to automate PowerPoint using VB

    Microsoft has an article that explains how to automate PowerPoint using VB For some odd reason they' ...

  5. F - Piggy-Bank 完全背包问题

    Before ACM can do anything, a budget must be prepared and the necessary financial support obtained. ...

  6. 登陆模块,这个是很重要的模块,有shiro和spring security专门的权限认证框架

    登陆模块,这个是很重要的模块,有shiro和spring security专门的权限认证框架

  7. Centos7: 设置UTC时区

    timedatectl set-timezone UTC

  8. Java字符编码的转化问题

    概述: 我想字符串的编码问题的确会困扰到非常多开发人员.我近期也是被困扰到了. 问题是这种,我们通过二维码扫描来获得二维码中的信息.可是.我们的二维码的产生过程却是"多样化"的.即 ...

  9. Andriod实现刮刮卡的效果

    思想: 将一个View设计成多层,内层(包含中奖信息)和外层(用于刮奖),外层的图层用Canvas与一个Bitmap关联,用这个关联的Bitmap来处理手势的滑动.类似于刮奖的动作. 使用paint. ...

  10. sqlite 数据库 相关知识

    一基本简单介绍 SQLite 是一个自持的(self-contained).无server的.零配置的.事务型的关系型数据库引擎.由于他非常小,所以也能够作为嵌入式数据库内建在你的应用程序中. SQL ...