参考Akka Essentials

 

1 Introduction to Akka

Actor Model

Actor模式的由来
In 1973, Carl Hewitt, Peter Bishop, and Richard Steiger wrote a paper—A Universal Modular ACTOR Formalism for Artificial Intelligence, which introduced the concept of Actors. Subsequently, the Actor Model was implemented in the Erlang language by Joe Armstrong and Ericsson implemented the AXD 301 telecom switch that went onto achieve reliability of 99.9999999 percent (nine 9's).

Actor模式改变传统oo的并发策略, 如下图
Actors change their state only when they receive a stimulus in the form of a message.
So unlike the object-oriented world where the objects are executed sequentially, the actors execute concurrently.

The Actor Model is based on the following principles:
• The immutable messages are used to communicate between actors.
Actors do not share state, and if any information is shared, it is done via message only.
Actors control the access to the state and nobody else can access the state. This means there is no shared, mutable state.
不可变消息, actor不会share自己的state, 只会通过不可变消息进行通信

• Each actor has a queue attached where the incoming messages are enqueued.
Messages are picked from the queue and processed by the actor, one at a time. An actor can respond to the received message by sending immutable messages to other actors, creating a new set of actors, updating their own state, or designating the computational logic to be used when the next message arrives (behavior change).
每个actor会有一个queue来接收message, actor会依次处理收到的message, 并发送消息给其他的actors

• Messages are passed between actors asynchronously.
It means that the sender does not wait for the message to be received and can go back to its execution immediately. Any actor can send a message to another actor with no guarantee on the sequence of the message arrival and execution.
消息是异步发送, actor不会保证消息到达或执行的顺序

• Communication between the sender and receiver is decoupled and asynchronous, allowing them to execute in different threads.
By having invocation and execution in separate threads coupled with no shared state, allows actors to provide a concurrent and scalable model.
这种低耦合和异步的方式, 很容易进行concurrent和扩展

 

Akka framework

The Akka framework has taken the Actor Model concept to build an event-driven, middleware framework that allows building concurrent, scalable, distributed systems. Akka uses the Actor Model to raise the abstraction level that decouples the business logic from low-level constructs of threads, locks, and non-blocking I/O.

Akka其实就是一种达到工业级别的Actor编程框架, 另外具有如下特性

The Akka framework provides the following features:
Concurrency: Akka Actor Model abstracts the concurrency handling and allows the programmer to focus on the business logic.
Scalability: Akka Actor Model's asynchronous message passing allows applications to scale up on multicore servers.
Fault tolerance: Akka borrows the concepts and techniques from Erlang to build a "Let It Crash" fault-tolerance model using supervisor hierarchies to allow applications to fail fast and recover from the failure as soon as possible.
Event-driven architecture: Asynchronous messaging makes Akka a perfect platform for building event-driven architectures.
Transaction support: Akka implements transactors that combine actors and software transactional memory (STM) into transactional actors. This allows composition of atomic message flows with automatic retry and rollback.
Location transparency: Akka treats remote and local process actors the same, providing a unified programming model for multicore and distributed computing needs.
Scala/Java APIs: Akka supports both Java and Scala APIs for building applications.

 

What is an actor?

Actor is modeled as the object that encapsulates state and behavior.
All the messages intended for the actors are parked in a queue and actors process the messages from that queue

 

State and Behavior

这个很容易理解, 如下图

actor需要确保state不会丢失, crash, 并可以被concurrency访问
Akka implements actors as a reactive, event-driven, lightweight thread that shields and protects the actor's state. Actors provide the concurrent access to the state allowing us to write programs without worrying about concurrency and locking issues.
When the actors fail and are restarted, the actors' state is reinitialized to make sure that the actors behave in a consistent manner with a consistent state.

 

Mailbox

用于存放收到message的地方, Akka提供多种类型的mailbox, 有限, 无限, 优先级

Akka provides multiple mailbox implementations. The mailboxes can be bounded or unbounded.
Akka provides a priority mailbox where the messages are enqueued based on the assigned priority.

 

Actor lifecycle
Actor定义preStart和postStop接口用于初始化和善后
Every actor that is defined and created has an associated lifecycle.
Akka provides hooks such as preStart that allow the actor's state and behavior to be initialized.
When the actor is stopped, Akka disables the message queuing for the actor before PostStop is invoked. In the postStop hook, any persistence of the state or clean up of any hold-up resources can be done:

 

Fault tolerance

首先是actor hierarchy, 看看右图以项目管理为例
分而治之, 每个actor都有自己明确的职责, 不会去干涉和了解别人的工作, 大家通过message或输出物来沟通
同时PM需要监督和管理项目进行, 如果actor发现自己处理不了的message或error, 需要向上级反映以得到帮助
并且Akka actor都只会有一个supervisor

Akka的fault-tolerance就是基于actor hierarchy和supervisor model

The whole idea is to break down the task into smaller tasks to the point where the task is granular and structured enough to be performed by one actor.
Each actor knows which kind of message it will process and how he reacts in terms of failure.
So, if the actor does not know how to handle a particular message or an abnormal runtime behavior, the actor asks its supervisor for help. The recursive actor hierarchy allows the problem to be propagated upwards to the point where it can be handled.
Remember, every actor in Akka has one and only one supervisor.
This actor hierarchy forms the basis of the Akka's "Let It Crash" fault-tolerance model.
Akka's fault-tolerance model is built using the actor hierarchy and supervisor model.

 

Location transparency

Akka通过配置来透明化actor的位置
Akka uses configuration to indicate whether the actor is running locally or on a remote machine.
Akka uses the actor hierarchy and combines it with the actor system address to make each actor identifiable and reachable.

 

总结

As we move ahead and delve deep into the constructs provided by the Akka framework, we need to make sure that we keep in mind the following concepts:
• An actor is a computation unit with state, behavior, and its own mailbox
• There are two types of actors—untyped and typed
• Communication between actors can be asynchronous or synchronous
• Message passing to the actors happens using dispatchers
• Actors are organized in a hierarchy via the actor system
• Actors are proxied via ActorRef
• Supervisor actors are used to build the fault-tolerance mechanism
• Actor path follows the URL scheme, which enables location transparency
• STM is used to provide transactional support to multiple actor state updates

 

2 Starting with Akka

这章写的非常好, 非常详细的描述的Akka的环境搭建, 需要可以参考, 这儿就不列了
并且通过一个例子来告诉你Akka怎么用, 最给力的是给出了Java和Scala两个版本, 估计比一下, 谁都想把java扔到垃圾堆去

 

要解决的问题很简单, 对句子分词, 统计, 最后aggregate的过程

对应到Actor基本就是下面的过程,

看看scala怎么实现的, 很清晰, 一下就对Akka有个全局的概念

 

定义Message类, 为了后面用模式匹配, 加上case

sealed trait MapReduceMessage
case class WordCount(word: String, count: Int) extends MapReduceMessage
case class MapData(dataList: ArrayBuffer[WordCount]) extends MapReduceMessage
case class ReduceData(reduceDataMap: Map[String, Int]) extends MapReduceMessage
case class Result extends MapReduceMessage

 

MapActor.scala

package akka.first.app.mapreduce.actors
import akka.actor.Actor
import akka.actor.ActorRef
import akka.first.app.mapreduce.MapData
import akka.first.app.mapreduce.WordCount
import scala.collection.mutable.ArrayBuffer
class MapActor extends Actor {
val STOP_WORDS_LIST = List("a", "am", "......", "to") //stopword,列出部分
val defaultCount: Int = 1
def receive: Receive = {
case message: String => //匹配string,即原始的句子
sender ! evaluateExpression(message) //将结果发送给reduceActor
}
def evaluateExpression(line: String): MapData = MapData {
line.split("""\s+""").foldLeft(ArrayBuffer.empty[WordCount]) {//比较奇葩的操作, 类似reduce
(index, word) =>
if(!STOP_WORDS_LIST.contains(word.toLowerCase))
index += WordCount(word.toLowerCase, 1)
else
index
}
}
}

 

ReduceActor.scala

package akka.first.app.mapreduce.actors
import scala.collection.immutable.Map
import akka.actor.Actor
import akka.first.app.mapreduce.MapData
import akka.first.app.mapreduce.ReduceData
import akka.first.app.mapreduce.WordCount
class ReduceActor extends Actor {
def receive: Receive = {
case MapData(dataList) => //匹配MapData message类
sender ! reduce(dataList) //发送到aggregator
}
def reduce(words: IndexedSeq[WordCount]): ReduceData = ReduceData {
words.foldLeft(Map.empty[String, Int]) { (index, words) => //又使用foldLeft
if (index contains words.word)
index + (words.word -> (index.get(words.word).get + 1))
else
index + (words.word -> 1)
}
}
}

 

AggregateActor.scala

package akka.first.app.mapreduce.actors
import scala.collection.immutable.Map
import scala.collection.mutable.HashMap
import akka.actor.Actor
import akka.first.app.mapreduce.ReduceData
import akka.first.app.mapreduce.Result
class AggregateActor extends Actor {
val finalReducedMap = new HashMap[String, Int] //存放统计结果
def receive: Receive = { //需要处理两种message
case ReduceData(reduceDataMap) => //ReduceData Message, 需要aggregate
aggregateInMemoryReduce(reduceDataMap)
case Result => //结果请求
sender ! finalReducedMap.toString()
}
def aggregateInMemoryReduce(reducedList: Map[String, Int]): Unit = {
for ((key,value) <- reducedList) {
if (finalReducedMap contains key)
finalReducedMap(key) = (value + finalReducedMap.get(key).get)
else
finalReducedMap += (key -> value)
}
}
}

 

MasterActor.scala

Supervisor负责协调各个actors

package akka.first.app.mapreduce.actors
import akka.actor.Actor
import akka.actor.ActorRef
import akka.actor.Props
import akka.first.app.mapreduce._
import akka.routing.RoundRobinRouter
class MasterActor extends Actor {
//定义各个actor, 用context.actorOf
val mapActor = context.actorOf(Props[MapActor].withRouter(
RoundRobinRouter(nrOfInstances = 5)), name = "map")
val reduceActor = context.actorOf(Props[ReduceActor].withRouter(
RoundRobinRouter(nrOfInstances = 5)), name = "reduce")
val aggregateActor = context.actorOf(Props[AggregateActor], name = "aggregate")
def receive: Receive = {
case line: String =>
mapActor ! line
case mapData: MapData =>
reduceActor ! mapData
case reduceData: ReduceData =>
aggregateActor ! reduceData
case Result =>
aggregateActor forward Result
}
}

 

MapReduceApplication.scala

整个执行程序

package akka.first.app.mapreduce
import scala.collection.immutable.Map
import scala.collection.mutable.ArrayBuffer
import akka.actor.actorRef2Scala
import akka.actor.ActorSystem
import akka.actor.Props
import akka.dispatch.Await
import akka.first.app.mapreduce.actors.MasterActor
import akka.pattern.ask
import akka.util.duration.intToDurationInt
import akka.util.Timeout sealed trait MapReduceMessage
case class WordCount(word: String, count: Int) extends MapReduceMessage
case class MapData(dataList: ArrayBuffer[WordCount]) extends MapReduceMessage
case class ReduceData(reduceDataMap: Map[String, Int]) extends MapReduceMessage
case class Result extends MapReduceMessage object MapReduceApplication extends App {
val _system = ActorSystem("MapReduceApp")
val master = _system.actorOf(Props[MasterActor], name = "master") //创建master actor
implicit val timeout = Timeout(5 seconds)
master ! "The quick brown fox tried to jump over the lazy dog and fell on the dog"
master ! "Dog is man's best friend"
master ! "Dog and Fox belong to the same family"
Thread.sleep(500)
val future = (master ? Result).mapTo[String]
val result = Await.result(future, timeout.duration)
println(result)
_system.shutdown
}

Akka Essentials - 1的更多相关文章

  1. Akka Essentials - 2

    Actors Defining an actor class MyActor extends Actor { def receive = { } } In Scala, the receive blo ...

  2. akka构建简单分布式应用

    http://www.cnblogs.com/hequn/articles/3764630.html 当程序的要求达到一台计算机的极限时,我们便需要将程序分布式化,让程序运行在多台计算机上.akka提 ...

  3. 2014.8.12-AKKA和Actor model 分布式开发环境学习小结

    学习使用AKKA 断断续续有一年了. 眼下还是习惯用java来写akka以下的程序.对于原生的scala还是没有时间和兴趣去学习它. 毕竟学习一门语言须要兴趣和时间的. AKKA学习资源还是不算丰富. ...

  4. Akka.net路径里的user

    因为经常买双色球,嫌每次对彩票号麻烦,于是休息的时候做了个双色球兑奖的小程序,做完了发现业务还挺复杂的,于是改DDD重做设计,拆分服务,各种折腾...,不过这和本随笔没多大关系,等差不多了再总结一下, ...

  5. Aaron Stannard谈Akka.NET 1.1

    Akka.NET 1.1近日发布,带来新特性和性能提升.InfoQ采访了Akka.net维护者Aaron Stannard,了解更多有关Akka.Streams和Akka.Cluster的信息.Aar ...

  6. Akka.NET v1.0 已发布,支持Mono

    Akka.NET 是Java/Scala 流行框架Akka的一个 .NET 开源移植.可用于构建高并发,分布式和容错事件驱动的应用在 .NET 和 Mono 平台之上.Akka.NET 经过一年多的努 ...

  7. AKKA 笔记 - 有限状态机 -2

    AKKA 笔记 - 有限状态机 -2 原文地址: http://rerun.me/2016/05/22/akka-notes-finite-state-machines-2/ 在上一节的Akka FS ...

  8. [翻译]AKKA笔记 - 有限状态机 -1

    原文地址:http://rerun.me/2016/05/21/akka-notes-finite-state-machines-1/ 我最近有个机会在工作上使用了Akka FSM,是个非常有趣的例子 ...

  9. [翻译]AKKA笔记 -ACTOR SUPERVISION - 8

    失败更像是分布式系统的一个特性.因此Akka用一个容忍失败的模型,在你的业务逻辑与失败处理逻辑(supervision逻辑)中间你能有一个清晰的边界.只需要一点点工作,这很赞.这就是我们要讨论的主题. ...

随机推荐

  1. CentOS6X安装PHP5.5

    CentOS6.x默认的php版本是php5.3,已经过时喽,现在最新的稳定版是5.5.38. 安装方法: 1.先下载2个源 rpm -Uvh https://dl.fedoraproject.org ...

  2. Atitit.md5 实现原理

    Atitit.md5 实现原理 1. 算法流程图2 2. MD5算法过程:2 2.1. 3. 处理分组数据3 3. MD5加密字符串实例5 4. Md5的历史7 4.1.1. MD27 4.1.2. ...

  3. (3)Smali系列学习之Smali语法详解

    数据类型 Dalvik字节码只有两种格式:基本类型和引用类型.对象和数组属于引用类型 语法 含义 V void,只用于返回值类型 Z boolean B byte S short C char I i ...

  4. ECC加密算法原理入门介绍

    前言 同RSA(Ron Rivest,Adi Shamir,Len Adleman三位天才的名字)一样,ECC(Elliptic Curves Cryptography,椭圆曲线密码编码学)也属于公开 ...

  5. VMWare虚拟机端口转发

    # VMWare虚拟机端口转发 虚拟机和宿主机共用主机IP对外提供服务,又不想提供给虚拟机独立IP,使用VM虚拟机提供的端口转发功能正合适. ### 端口转发--------------------- ...

  6. Github上Fork代码,及源码修改

    iOS开发中经常遇到这种情况,你使用的第三方库不能完全满足自己项目需要,只能修改源码来解决. 我们以前的解决办法是,添加到项目中直接修改源码.这样就有一个问题,不能和源库同步,当作者更新后你不能(po ...

  7. 【转载】【Pycharm编辑器破解步骤】之idea和Pycharm 等系列产品激活激活方法和激活码(附:Mac系统)

    感谢:雪中皓月的<idea和Pycharm 等系列产品激活激活方法和激活码> 第一种方法:使用现有的注册服务器 优点:快捷,方便,省事 缺点:经常被封杀,可能会面临经常激活的困扰 Lice ...

  8. C语言 函数指针一(函数指针的定义)

    //函数指针 #include<stdio.h> #include<stdlib.h> #include<string.h> //函数指针类型跟数组类型非常相似 / ...

  9. npm install 不自动生成 package-lock.json文件

    package-lock.json这个文件的作用就不详细说明了 有需要的可以参考 :https://www.cnblogs.com/cangqinglang/p/8336754.html 网上都说 n ...

  10. 蓝桥杯 第三届C/C++预赛真题(8) 密码发生器(水题)

    在对银行账户等重要权限设置密码的时候,我们常常遇到这样的烦恼:如果为了好记用生日吧,容易被破解,不安全:如果设置不好记的密码,又担心自己也会忘记:如果写在纸上,担心纸张被别人发现或弄丢了... 这个程 ...