akka设计模式系列(Actor模型)
谈到Akka就必须介绍Actor并发模型,而谈到Actor就必须看一篇叫做《A Universal Modular Actor Formalism for Artificial Intelligence 》的论文,它最早发表于1973年,提出了一种并发计算的理论模型,Actor就源于该模型。
在Actor模型中,actor是一个并发原语,简单的说,一个actor就是一个工人,与进程或线程一样都能够工作或处理任务。其实这还有点不好理解,我们可以把它想象成面向对象编程语言中的一个对象实例。在OOP中一个对象可以访问或修改另一个对象的属性,也可以直接调用另一个对象的方法。例如下图,person1给person2发送了一个消息,直接调用方法就行了。深入底层执行逻辑的话,结果就是JVM转到sayHello的代码区,一步步执行。
public class HelloWorld {
private String name = "";
public HelloWorld(String name){
this.name = name;
}
public String getName(){
return this.name;
}
public void sayHello(HelloWorld to, String msg){
System.out.println(to.getName()+" 收到 "+name+" 的消息:"+ msg);
}
} public class OOPInvoke {
public static void main( String[] args ) {
HelloWorld person1 = new HelloWorld("Person1");
HelloWorld person2 = new HelloWorld("Person2");
person1.sayHello(person2,"Hello world");
}
}
sayHello在一个线程中执行基本没有问题,但是多个线程执行时,就可能出问题了,因为在执行sayHello的时候person2的name值可能被其他线程修改。这是一个name字段,意外修改没有关系,但如果是一个金额字段呢?
actor和对象的不同之处在于,actor的状态不能直接读取、修改,actor的方法不能直接调用。actor只能通过消息传递的方式与外界通信。每个对象都有一个this指针,代表对象的地址,可以通过该地址调用方法或存取状态;与此类似,actor也有一个代表本身的地址,但只能向该地址发送消息。
简单点说,actor通过消息传递的方式与外界通信。消息传递是异步的。每个actor都有一个邮箱,该邮箱接收并缓存其他actor发过来的消息,actor一次只能同步处理一个消息,处理消息过程中,除了可以接收消息,不能做任何其他操作。前面这段话,我加粗、倾斜、加下划线、还用红色字体标出,你就应该知道有多重要了,这就是actor模型的本质。
Actor模型的另一个好处就是可以消除共享状态,因为它每次只能处理一条消息,所以actor内部可以安全的处理状态,而不用考虑锁机制。标红的这两句话如果可以理解透彻,基本上Actor模型的精髓你就掌握了。
那么读者可能会问,每次只处理一个消息,这不是会严重的影响性能么?废话,一次处理一个消息当然影响性能了。不过,如果你恰当的运用Akka和Actor模型,完全可以不必关心性能的问题。下面是Actor模型的几个基本原则:
(1)所有的计算都是在actor中执行的
(2)actor之间只能通过消息进行通信交流
(3)为了响应消息,actor可以进行下列操作
a. 更改状态或行为
b. 发消息给其他actor
c. 创建有限数量的子actor
看了上面几个基本原则,你是不是更加鉴定的认为Actor模型没啥用?嗯,这就对了,因为我当初也是这么认为的。一次处理一个消息,没有并发,怎么提高性能;如果actor只能更改状态或行为,发消息给其他actor,创建有限数量的子actor,那我的业务逻辑在哪里;actor之间只能通过消息通信,我怎么知道另外一个actor的地址。其实吧,如果你能问到这几个问题,那么恭喜你,你非常需要我这个博客系列,我会一一进行分析,把我之前的坑展示给你看,以确保你不会再掉进去。
其实Actor模型出现的很早,而20世纪80年代,爱立信在Erlang中实现了Actor模型,用于嵌入式电信应用程序。该实现中引入了监督机制提供的容错性概念。爱立信使用Erlang和Actor模型实现了一款日后经常被提及的应用:AXD301。这玩意儿能提供99.9999999% 的可用性,看到没,7个9!!!绝对可以亮瞎人们的狗眼,这意味着在100年的时间中,AXD301只有3.1秒的时间会宕机。
Actor模型的另一个重要的特性就是容错,它通过监督机制提供容错。这跟java中的throw exception有点类似,都是把处理响应错误的责任交给出错对象以外的实体。但在java中如果一个程序或者线程抛出了一个异常,你敢放心的恢复对应的程序或线程吗?你确保恢复之后还能正常的运行吗,毕竟需要很多资源需要重新创建。但Actor模型可以!
如上图所示actor之间是有层级关系的,子actor如果出现了异常会抛给父actor,父actor会根据情况重新构建子actor,子actor从出现异常,到恢复之后正常运行,这段时间内的所有消息都不会丢失,等恢复之后又可以处理下一个消息。也就是说如果一个actor抛出了异常,除了导致发生异常的消息外,任何消息都不会丢失。这容错性当然好了。当然了,为了实现这种特性,akka或者Erlang需要做很多工作的。
Akka中的Actor模型还有另外一个比较重要的两个特性:分布式与位置透明性。其实可以认为这是一个特性。Actor模型中一个很重要的概念就是actor地址,因为其他actor需要通过这个地址与actor进行通信。akka考虑到分布式的网络环境,对actor地址进行了抽象,屏蔽了本地地址和远程地址的差异,对于开发者来说基本上是透明的。由于actor地址是透明的,那么akka有引入了集群。当然了基于Actor模型和位置透明性,Akka还有其他很多有用的组件,这里就不介绍了,后面会详细说明。
关于Actor模型就先介绍到这里,下一章节我们会介绍Actor模型的最基本的设计模式,以说明该模型的适用场景。
akka设计模式系列(Actor模型)的更多相关文章
- akka设计模式系列-消息模型(续)
在之前的akka设计模式系列-消息模型中,我们介绍了akka的消息设计方案,但随着实践的深入,发现了一些问题,这里重新梳理一下设计方法,避免之前的错误.不当的观点给大家带来误解. 命令和事件 我们仍然 ...
- akka设计模式系列-actor锚定
actor锚定模式是指使用actorSelection对acor进行锚定的设计模式,也可以说是一个对actor的引用技巧.在某些情况下,我们可能需要能够根据Actor的path锚定对应的实例.简单来说 ...
- akka设计模式系列-消息模型
通过前面的文章我们总结了几个常见的actor设计模式,但此处不得不提前介绍一下在Akka中消息的设计模式.随着对Akka的使用,我们会发现,使用Akka设计系统其实就是面向消息编程.actor之间消息 ...
- akka设计模式系列
由于本人爱好Scala,顺便也就爱好Akka,但目前网上对Akka的介绍大多都是概念上或技术方向上的介绍,基本没有Akka设计模式或者Actor模型设计模式的资料.这对于Akka的普及非常不利,因为即 ...
- akka设计模式系列-慎用ask
慎用ask应该是Akka设计的一个准则,很多时候我们应该禁用ask.之所以单独把ask拎出来作为一篇博文,主要是akka的初学者往往对ask的使用比较疑惑. "Using ask will ...
- Akka简介与Actor模型
Akka是一个构建在JVM上,基于Actor模型的的并发框架,为构建伸缩性强,有弹性的响应式并发应用提高更好的平台.本文主要是个人对Akka的学习和应用中的一些理解. Actor模型 Akka的核心就 ...
- akka设计模式系列-While模式
While模式严格来说是while循环在Akka中的合理实现.while是开发过程中经常用到的语句之一,也是绝大部分编程语言都支持的语法.但while语句是一个循环,如果循环条件没有达到会一直执行wh ...
- Akka简介与Actor模型(一)
前言...... Akka是一个构建在JVM上,基于Actor模型的的并发框架,为构建伸缩性强,有弹性的响应式并发应用提高更好的平台.本文主要是个人对Akka的学习和应用中的一些理解. Actor模型 ...
- akka设计模式系列-Backend模式
上一节我们介绍了Akka使用的基本模式,简单点来说就是,发消息给actor,处理结束后返回消息.但这种模式有个缺陷,就是一旦某个消息处理的比较慢,就会阻塞后面所有消息的处理.那么有没有方法规避这种阻塞 ...
随机推荐
- Ubuntu---vim配置
1. Linux g++开启C++11支持 1.1 使用vim打开.bashrc文件 sudo vim ~/.bashrc 1.2 在some more ls aliases注释块的地方添加: ali ...
- ecshop笔记
***ecshop在线入门手册***:http://book.ecmoban.com/ 解决ecshop与jquery冲突问题1.修改文件:/js/transport.js在文件最底部增加代码: if ...
- C语言结构体用法
结构体的定义: 方法一: struct student { char name[10]; int age; int number; }; struct student stu1; 方法二: struc ...
- SQL学习笔记:一些高级语句
现在以MySQL为模板.学习的方法和别的数据库写法上会有不同,但是思路基本一致. 用到的数据库表的格式: +----+--------------+-------------------------- ...
- HDU 1081 DP找最大和的矩阵
题目大意: 在一个给定的大矩阵中找一个小型的矩阵,使这个矩阵中的元素和最大 可以先来看下面这个问题: 原来有做过在一个给定的数字序列中找一个最大和子序列,核心代码如下: ]; ]; ; ; int r ...
- hdu 1867 kmp匹配
#include<stdio.h> #include<string.h> #define N 100100 void getnext(int next[],char s[]) ...
- Ubuntu查看系统版本的方法
1. less /etc/issue 2. less /proc/version 3. uname -a 4. lsb_release -a
- php 生成订单号
最近在练手一个订单提交的小项目,需要用到生成订单号,网上找了下,觉得这个最好. function build_order_no(){ return date('Ymd').substr(implode ...
- [LeetCode] 035. Search Insert Position (Medium) (C++)
索引:[LeetCode] Leetcode 题解索引 (C++/Java/Python/Sql) Github: https://github.com/illuz/leetcode 035. Sea ...
- Python基础--基本文件操作
全部的编程语言都一样,学完了一些自带的数据机构后,就要操作文件了. 文件操作才是实战中的王道. 所以,今天就来分享一下Python中关于文件的一些基本操作. open方法 文件模式 这个模式对于写入文 ...