什么才是真正的akka actor模型型

看Erlang中Actor模型的执行方式和优劣
看Erlang中Actor模型的执行方式和优劣
  Actor模型为并行而生。由于现在单台机器中独立的计算单元也越来越多,Actor模型的重要性也越来越大。Actor模型的理念非常简单:天下万物皆为Actor,Actor之间通过发送消息进行通信。不同的Actor可以同时处理各自的消息,从而获得了大规模的并发能力。
  Erlang基于Actor模型实现,我们甚至可以这样认为,没有Erlang在业界竖立的丰碑,Actor模型便不会如此受人关注。目前,几乎所有的主流开发平台上都有了Actor模型的实现,如Java平台下的Jetlang以及.NET平台下的MS CCR和Retlang;还有一些Actor框架专为特定语言设计,如F#的MailboxProcessor以及Scala的Actor类库;甚至微软还基于MS CCR构建了一门新的语言Axum。
  不过对于.NET平台下的开发人员来说,我们最常用的语言是C#。无论您是在使用MS CCR还是Retlang(亦或是我写的ActorLite),在消息的执行阶段总是略显尴尬。本文的目的便是提出一种适合C# Actor的消息执行方式,而这种执行方式还会成为我以后公开的C#中“模式匹配”的基础。
  Erlang中的执行方式
  本文将分为三个部分,您目前正在阅读的第一部分,将会观察Erlang是如何执行消息的。有对比才会有差距,也正是由于Erlang在Actor模型上的示范作用,我们才会意识到C# Actor在使用上有多么的不方便。
  作为示例,我们还是使用最经典的乒乓测试。乒乓测试的效果很简单:ping和pong为两个Actor对象,首先由ping向pong发送一个“Ping”消息,pong在接受到Ping消息之后,将会向ping发送一个“Pong”消息。在双方“乒来乓去”几个回合后,ping将会向pong发起“Finished”,从而停止交互。
  乒乓测试的Erlang的实现代码如下:    -module(tut15). &  &  -export([start/0,&ping/2,&pong/0]). &  &  ping(0,&Pong_PID)&-& &  &&&&Pong_PID&!&finished, &  &&&&io:format("ping&finished~n",&[]); &  &  ping(N,&Pong_PID)&-& &  &&&&Pong_PID&!&{ping,&self()}, &  &&&&receive &  &&&&&&&&pong&-& &  &&&&&&&&&&&&io:format("Ping&received&pong~n",&[]) &  &&&&end, &  &&&&ping(N&-&1,&Pong_PID). &  &  pong()&-& &  &&&&receive &  &&&&&&&&finished&-& &  &&&&&&&&&&&&io:format("Pong&finished~n",&[]); &  &&&&&&&&{ping,&Ping_PID}&-& &  &&&&&&&&&&&&io:format("Pong&received&ping~n",&[]), &  &&&&&&&&&&&&Ping_PID&!&pong, &  &&&&&&&&&&&&pong() &  &&&&end. &  &  start()&-& &  &&&&Pong_PID&=&spawn(tut15,&pong,&[]), &  &&&&spawn(tut15,&ping,&[3,&Pong_PID]). &
  由于Erlang的函数式编程,尾递归,receive原语等特殊的语言特性,其乒乓测试的实现或语义上可能和其他语言有一定区别。不过我们现在还是关注Erlang在消息执行时的特性:模式匹配。
  虽然Erlang有诸多优秀特性,但是它的数据抽象能力非常有限。在Erlang中常用的数据结构只有三种:
  原子(atom):原子使用小写开头的标识符来表示。您可以把原子认为是一种字符串常量来看待,事实上它除了作为标识之外也没有额外的作用。
  绑定(binding):大写开头的标示符则为绑定,您可以近似地将其理解为“只能设置一次”的变量。一个绑定内部可以保存任何数据,如一个进程(Erlang的概念,并非指操作系统进程)的id,一个数字,或一个字符串。
  元组(tuple):顾名思义,“元组”即为“单元的组合”,单元即为“原子”,“绑定”以及其他“元组”,通过某种方式结合起来。如上述代码中{ping, Ping_PID}便是一个由原子“ping”和绑定“Ping_PID”组成。当然您也可以写成{do, {ping, Hello, World}, 7}这种嵌套的元组结构。
  Erlang中的receive原语的作用是接受下一条消息,直到有可用消息时它才会执行下面的代码。Erlang使用了模式匹配(Pattern Matching)来表现接受到不同消息时的逻辑分支。如pong的实现:    pong()&-& &  &&&&receive &  &&&&&&&&finished&-& &  &&&&&&&&&&&&io:format("Pong&finished~n",&[]); &  &&&&&&&&{ping,&Ping_PID}&-& &  &&&&&&&&&&&&io:format("Pong&received&ping~n",&[]), &  &&&&&&&&&&&&Ping_PID&!&pong, &  &&&&&&&&&&&&pong() &  &&&&end.&
  在这段代码中,receive将会设法将消息与两种模式进行匹配:
  原子finished,表示测试结束。
  元组{ping, Ping_PID},表示一个元组,其中有两个单元,首先是ping原子,其次是Ping_PID绑定。
  在成功匹配了某个模式之后,其中的绑定也会随之被赋上特定的值。如匹配了{ping, Ping_PID}之后,Ping_PID便被赋值为ping这个Actor对象的标识符。而在接下来的逻辑中,便可以使用这些“绑定”中的值。由于元组的结构不会受到任何限制,因此开发人员可以使用它来表示任意的抽象数据类型――更确切地说,应该是“数据结构”吧。
  Erlang的优势与缺陷
  Erlang在消息执行方式上的优势在于灵活。Erlang是弱类型语言,在实现的时候可以任意调整消息的内容,或是模式的要求。在Erlang进行模式匹配时往往有种约定:使用“原子”来表示“做什么”,而使用“绑定”来获取操作所需要的“数据”,这种方式避免了冗余的cast和赋值,在使用的时候颇为灵活。然而,世上没有完美的事物,Erlang的消息执行方式也有缺陷,而且是较为明显的缺陷。
  首先,Erlang的数据抽象能力实在太弱。如果编写一个略显复杂的应用程序,您会发现程序里充斥着复杂的元组。您可能会疲于应对那些拥有7、8个单元(甚至跟多)的元组,一个一个数过来到底某个绑定匹配的是第几项,它的含义究竟是什么――一旦搞错,程序便会出错,而且想要调试都较为困难。因此,也有人戏称Erlang是一门“天生会损害人视力的语言”(令人惊讶的是,那篇文章居然搜不到了,我们只能从搜索引擎上看出点痕迹了)。
  而我认为,这并不是Erlang语言中最大的问题,Erlang中最大的问题也是其“弱类型”特性。例如,现在有一个公用的Service Locator服务,任意类型的Actor都会像SL发送一个消息用于请求某个Service的位置,SL会在得到请求之后,向请求方发送一条消息表示应答。试想,如果SL的功能需要有所修改,作为回复的消息结构产生了变化,那么我们势必要修改每一个请求方中所匹配的模式。由于消息的发送方和接受方在实际上完全分离,没有基于任何协议,因此静态检查几乎无从做起。一旦遇到这种需要大规模的修改的情况,Erlang程序便很容易产生差错。因为一旦有所遗漏,系统便无法正常执行下去了。
  您对Erlang的感觉如何?这是一门会影响您编程思维的语言。老赵建议,即使您平时不会使用Erlang,也不妨简单接触一下这门语言。它的并发或容灾等特性给了我许多启示。相信您会有不少收获。
H3C认证Java认证Oracle认证
基础英语软考英语项目管理英语职场英语
.NETPowerBuilderWeb开发游戏开发Perl
二级模拟试题一级模拟试题一级考试经验四级考试资料
港口与航道工程建设工程法规及相关知识建设工程经济考试大纲矿业工程市政公用工程通信与广电工程
操作系统汇编语言计算机系统结构人工智能数据库系统微机与接口
软件测试软件外包系统分析与建模敏捷开发
法律法规历年试题软考英语网络管理员系统架构设计师信息系统监理师
高级通信工程师考试大纲设备环境综合能力
路由技术网络存储无线网络网络设备
CPMP考试prince2认证项目范围管理项目配置管理项目管理案例项目经理项目干系人管理
Powerpoint教程WPS教程
电子政务客户关系管理首席信息官办公自动化大数据
职称考试题目
就业指导签约违约职业测评
招生信息考研政治
网络安全安全设置工具使用手机安全
3DMax教程Flash教程CorelDraw教程Director教程
Dreamwaver教程HTML教程网站策划网站运营Frontpage教程
生物识别传感器物联网传输层物联网前沿技术物联网案例分析
互联网电信IT业界IT生活
Java核心技术J2ME教程
Linux系统管理Linux编程Linux安全AIX教程
Windows系统管理Windows教程Windows网络管理Windows故障
组织运营财务资本
视频播放文件压缩杀毒软件输入法微博
数据库开发Sybase数据库Informix数据库
&&&&&&&&&&&&&&&
希赛网 版权所有 & &&主题信息(必填)
主题描述(最多限制在50个字符)
申请人信息(必填)
申请信息已提交审核,请注意查收邮件,我们会尽快给您反馈。
如有疑问,请联系
关注云计算OpenStack、Docker、SaaS领域
寻找程序员欧巴,UI设计狮,软件众包……欢迎来勾搭~
微信号:waibaome1让天下没有难学的技术
作者:Paul Butcher
译者:黄炎
出品方:图灵
出版社:人民邮电出版社 (感谢图灵授权发布此文)
使用actor就像租车——我们如果需要,可以快速便捷地租到一辆;如果车辆发生故障,也不需要自己修理,直接打电话给租车公司更换另外一辆即可。
actor模型是一种适用性非常好的通用并发编程模型。它可以应用于共享内存架构和分布式内存架构,适合解决地理分布型的问题。同时它还能提供很好的容错性。
(1 votes, average: 5.00 out of 5)
Loading...
译者:Zhanggc
审校:吴京润
角色模型对编写并发、分布式系统进行了高度抽象。它减轻了开发者必须对互斥锁与线程管理的负担,更容易编写出正确的并发与并行系统。早在1973 年 Carl Hewitt 发表的论文中定义了角色,但一直流行于Erlang 语言中,随后被爱立信公司应用于建立高并发、可靠通信系统,取得了巨大成功。
Akka 框架里面角色的API 跟Scala 框架里面角色相似,后者一些语法曾经模仿Erlang语言。
(4 votes, average: 4.50 out of 5)
Loading...
译者:小鱼
审校者:吴京润
2.5 角色的引用、路径和地址
这一章描述,角色在一个有可能是分布式的角色系统中是如何被识别和定位的。它关系到了形成的内在监管层级以及角色跨越多个网络节点之间通信的位置透明化。
(1 votes, average: 5.00 out of 5)
Loading...
声明:本文是《》的第五章,感谢华章出版社授权发布此文,禁止以任何形式转载此文。
基于角色的并发模型降低了隔离可变性编程的难度,但该模型在适用场景上还是存在一些限制。
由于角色是通过消息来进行彼此间通信的,所以在那些没有强制不可变性的语言中,我们就必须人工来保证消息都是不可变的。传递可变消息将导致线程安全问题并最终使整个应用陷入共享可变性的险境当中,所以当手头的辅助工具还没有发展到可以帮助我们自动查验消息的不可变性之前,保证消息不可变性的重担暂时还是得由我们程序员来肩负。
(1 votes, average: 1.00 out of 5)
Loading...
声明:本文是《》的第五章,感谢华章出版社授权发布此文,禁止以任何形式转载此文。
截至目前我们所写的关于角色的例子中,所有角色及其客户端都运行于同一JVM进程中。但在现实生活中,有一部分开发者认为角色也应该像在Erlang中那样被用于进程间通信。而另一部分开发者则像我们在前面所演示的那样只将其应用于进程内通信。值得说明的一点是,Scala和Akka同时兼顾了这两个阵营的需求。
在Akka中,远程角色的用法与进程内角色的用法十分相似,唯一的区别就在于我们如何访问角色。Akka在底层使用了JBoss Netty和Google Protocol Buffers库来实现远程操作与本地调用的无缝衔接,使我们可以跨越进程边界,将任意角色所产生的序列化消息和引用传递给任意的远程角色。Akka提供了通过编程和配置选项两种方式来配置主机名、端口号、消息帧的大小、安全设置等配置信息。这些配置信息的详情可以参阅Akka的帮助文档,为了简单起见,在本节的示例中我们将只使用默认设置。
(还没有评分)
Loading...
声明:本文是《》的第五章,感谢华章出版社授权发布此文,禁止以任何形式转载此文。
正如我们在8.7节中所看到的那样,类型化角色是吸取了面向对象的程序设计和基于角色的程序设计二者的精华所孕育出来的新编程模型。该编程模型集所有我们耳熟能详的方法于一身,既可以方便地使用函数调用,又能享受角色所带来的好处。所以,在一个OO应用程序中,相比起普通的角色,我们可能会更倾向于使用类型化的角色。然而与普通角色相类似的是,类型化角色也是各自独立运行且不提供彼此间事务协调功能的,下面我们将会使用调和类型化角色(coordinating typed actor)来解决这个问题。
(3 votes, average: 2.33 out of 5)
Loading...
声明:本文是《》的第五章,感谢华章出版社授权发布此文,禁止以任何形式转载此文。
Akka transactor或事务角色为我们提供了一种将多个角色的执行过程合并到一个事务中的方法。顾名思义,transactor可以将多个角色对于托管STM Ref对象的更改变成原子操作,即仅当外围事务提交成功之后,对于那些托管对象的变更才能生效,否则所有的变更都会被丢弃。
Transactor提供了三种处理消息的方法:
默认情况下,Transactor会在其自己的事务中处理消息。
实现normally()函数。该函数不属于任何事物,其主要功能是独立地处理我们所选择的消息。
申请让消息被协调处理,即使其作为总控事务的一部分来执行。
总体而言,Transactor为我们提供了将其他角色链接到我们的协调事务里的弹性。此外,transactor还提供了前置和后置于事务的可选函数,以便于我们可以提前为事务做好准备或执行某些后置提交操作。
(2 votes, average: 1.00 out of 5)
Loading...
声明:本文是《》的第五章,感谢华章出版社授权发布此文,禁止以任何形式转载此文。
角色可以帮助我们对可变状态进行很好地隔离。尤其是当问题能够被拆分成可以独立运行的多个并发任务、并且并发任务彼此之间都是通过消息进行异步通信时,角色的表现更佳。但是,角色并未提供对跨任务的一致性进行管理的方法。所以如果我们希望两个或多个角色的动作要么全部成功、要么全部失败,则角色就无法独立实现,而此时我们就需要通过引入STM来与角色配合完成此类功能。在本节中,我假定你已经阅读过第6章、以及本章中有关角色和类型化角色的相关内容。
(还没有评分)
Loading...
声明:本文是《》的第五章,感谢华章出版社授权发布此文,禁止以任何形式转载此文。
使用了类型化角色的EnergySource使我们能够以调用函数的形式来掩盖后台顺序处理异步消息的过程,在实现了线程安全的同时又可以免去显式同步的困扰。虽然创建类型化角色并不困难,但此时我们的EnergySource却还是一个丢失了关键特性的半成品——即还没有可以周期性自动补充电量的能力。
(1 votes, average: 1.00 out of 5)
Loading...
声明:本文是《》的第五章,感谢华章出版社授权发布此文,禁止以任何形式转载此文。
到目前为止我们所接触过的角色都是可以接收消息的,而消息的类型也是五花八门,如String、元组、case类/自定义消息等。然而发送消息的行为在感觉上与我们日常编程工作中所使用的常规函数调用还是有很大区别的,为了弥合二者之间的鸿沟,类型化角色(Typed Actor)就应运而生了。这种类型的角色可以将发送消息的动作在形式上伪装成常规的函数调用,而将消息传输动作隐藏在后台执行。我们可以将类型化角色想像成为一个活动的对象,该对象运行在一个属于自己的轻量消息驱动的线程里面,并且还带有一个用于将正常的函数调用转换成异步非阻塞消息的拦截代理。
(1 votes, average: 1.00 out of 5)
Loading...
声明:本文是《》的第五章,感谢华章出版社授权发布此文,禁止以任何形式转载此文。
在使用基于角色的编程模型时,只有当多个角色互相协作、同心协力解决问题时,我们才能真正从中获益并感受到其中的乐趣。为了更好地利用并发的威力,我们通常需要把问题拆分成若干个子问题。不同的角色可以负责不同的子问题,而我们则需要对角色之间的通信进行协调。下面我们将通过重写计算目录大小的例子来学习如何在进行多角色协作。
(1 votes, average: 4.00 out of 5)
Loading...
声明:本文是《》的第五章,感谢华章出版社授权发布此文,禁止以任何形式转载此文。
通过前面的学习,我们已经了解了如何创建角色以及如何给角色发送消息,下面让我们来一起学习如何让多个角色协同工作。在第2章中,我们创建了一个统计给定区间内所有素数的程序。在该程序中,我们使用了ExecutorService、Callable、Future以及其他差不多超过一页纸那么多代码。本节我们将会学习如何用Akka角色对该示例进行重构,并且根据之前的惯例我们的介绍顺序还是先Java后Scala。
(2 votes, average: 1.00 out of 5)
Loading...
声明:本文是《》的第五章,感谢华章出版社授权发布此文,禁止以任何形式转载此文。
我们可以向角色发送任何类型的消息——String、Integer、Long、Double、List、Map、元组(tuples)、Scala的case类…但其中有一点需要注意的是,上述所有类型的消息都必须是不可变的。在上述这些类型中,我对于元组有着特殊的偏好,这并非因为我听到别人把元组误读成“two-ples”时感到很有趣,而是由于元组是轻量的、不可变的并且是最容易创建的实例之一。例如,在Scala中,我们可以简单地用(number1,number2)来创建一个含有两个数字的元组。除了元组之外,Scala的case类也是用来定义消息的理想类型——因为case类是不可变的、可以进行模式匹配并且还很容易进行复制。在Java中,我们可以通过将消息定义为一个不可修改(unmodifiable)的Collection的方式来将多个对象塞到一个消息中。当我们向角色传递消息时,如果发送者和接收者都在同一个JVM里,则默认情况下我们传递的是消息的引用。需要注意的是,保证所传递消息的不可变性是程序员自己的责任,尤其是当所发送的消息是我们自定义的类时则更需要加倍小心。为了解决这个问题,我们可以让Akka替我们先将消息序列化,然后将序列化出来的拷贝而不是原对象的引用发送出去,这样就可以避免由于类定义不严谨所造成的问题。
(3 votes, average: 2.33 out of 5)
Loading...
声明:本文是《》的第五章,感谢华章出版社授权发布此文,禁止以任何形式转载此文。
正如前面曾经提到过的那样,虽然我们有很多支持角色的类库可供选择,但是在本书中我们将使用Akka。这是一个基于Scala的类库,该类库拥有非常好的性能和可扩展性、并同时支持角色和STM。此外,该类库还可以被用于多种JVM上的语言中。在本章中,我们将注意力集中在Java和Scala身上。而在下一章,我们将会学习如何在其他语言中使用Akka的角色。
图 8-2 某个角色的生存周期
(还没有评分)
Loading...
声明:本文是《》的第五章,感谢华章出版社授权发布此文,禁止以任何形式转载此文。
角色是一种能够接收消息、处理请求以及发送响应的自由运行的活动(activity),主要被设计用来支持异步化且高效的消息传递机制。
每个角色都有一个内建的消息队列,该队列与手机上所使用的短信队列十分相似。假设Sally和Sean同时给Bob的手机发了短信,则运营商将会把这两条短信都保存起来以便Bob在方便的时候取走。类似地,基于角色的并发库允许多个角色并发地发送消息。默认情况下,消息发送者都是非阻塞的;它们会先把消息发送出去,然后再继续处理自己的业务逻辑。类库一般会让特定的角色顺序地拾取并处理消息队列中消息,只有将当前消息处理完或将消息委派给其他角色并发处理之后,这个角色才能够接收下一个消息。
(2 votes, average: 1.00 out of 5)
Loading...}

我要回帖

更多关于 actor模型 c 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信