Akka 设计Reactive System架构指南(A-Z翻译系列)

摘要

也许您已经听说过Akka,一种用于建造可伸缩,弹性且高效应用程序的工具包,支持Java和Scala编程语言。Akka包括了16个开源或商业的模块,帮助开发者构建从单JVM的Actor到网络分区修复,跨多个JVM的分布式集群等功能。如此多的特性,架构师和开发者如何从高层的角度理解Akka?读完本系列白皮书,您将更好的理解Akka “从A到Z”,这趟旅程从简单的Actor开始,直到集群系统结束,您将会学到以下知识:

  • Akka Actors如何运作,从创建系统到管理监督和路由
  • Akka 使用Akka Streams 和 Alpakka实现Reactive Streams的方式
  • 如何用Akka建造分布式集群系统,甚至集群中的集群
  • 对于分布式数据,分布式持久化,发布-订阅 和 ES/CQRS,Akka工具包如何通过多种组件提供开箱即用的解决方案
  • 可用的Akka商业版技术有哪些,它们是如何工作的

Akka的历史

Akka开始与1973(以IT世界的时间计算的话,相当于8000年前),在MIT的实验室,数学博士Carl Hewitt 合作发表了论文《A Universal Modular Actor Formalism for Artificial Intelligence》,在这篇论文中,介绍了一种数据模型,将actors作为并发计算的通用原子类型。

“提出Actor 模型是基于高度并行计算的前景,计算系统可能由成百上千的独立微处理器组成,每个处理器都拥有自己的本地内存和通讯处理器,可以通过高性能通讯网络在相互之间进行通讯”
--Carl Hewitt

在那个时候,跨多种云基础架构的低延迟并发计算在商业上并不可行,一直到企业级云计算的到来。
2009年,湾光公司的合伙人兼CTO Jonas Bonér,创建了Akka项目,希望在JVM上构造一种分布式,高并发,事件驱动的Actor模型实现,就像 Erlang语言实现的Actor模型一样。
现在到了2018年,离Akka十周年之剩一年之际,我们仍在继续我们的目标,将构建多核,异步,自愈,并且高伸缩性系统的能力带给Java和Scala的架构师和开发者,而无需关注所有隐藏在后的底层细节。


figure1.png

值得注意的是,Akka是一个JVM工具包,而不是一个框架(例如Play 或者 Lagom).虽然面临开源和商业组件的选择(Lightbend Enterprise Suite的一部分),本系列文章将关注在actors, streams,HTTP,集群,持久化和部署概念上。
这趟旅程将从独立的actors开始,介绍监督和自愈的行为模式,然后讲解通过Akka Streams, Akka HTTP 和 Alpakka实现Reactive Steams,再介绍事件Sroucing的分布式持久化和CQRS,微服务。最后到分布式集群以及如何管理,监控,编排集群。
了解了蓝图,让我们从Akka Actors开始吧。

第一部分 Akka Actors 及其工作方式

Actor 模型

让我们从Akka系统的原子或分子级别来看看actors,相对于大多数开发者来说,这是一种完全不同的编程方式。许多开发者学习过面向对象编程,甚至函数式编程,大多数情况下,这是必要的,同步方式编程设计到了很多线程和相关元素。
然而Actor 模型有很大不同,一个Actor本身是一个class,可以用Java或者Scala实现,actor具备方法,但是actor最大的不同在于actor的方法并不是在actor外部直接被别的类访问调用的。
不直接调用actor的方法,这需要改变原来的习惯。和actor交互的唯一方式是通过Akka提供的 actor system向actor发送消息。


figurep1-1.png

在actors中,actor之间消息是异步发送的,而不是同步的,如图一所示,消息首先存入待处理消息收件箱,actor遍历收件箱,一个一个地处理消息。这就是actor的基本机制,Akka系统就是由许多个actor构成,actor之间互相通过发送消息进行通讯。

figurep1-2.png

其工作原理如图2所示: actor A 发送消息给 actor B. 这是一个异步消息,就像两个人互相发送短信。A 发送给 B一条消息, A可以继续干别的事情,A并不会挂起等待B的回应,这和传统的面向对象的方法调用不一样,传统的方法调用必须等待方法返回。在这个例子中,A发了消息就继续往下执行了,或者执行别的代码,或者没有代码执行,啥也不干。


figurep1-3.png

在图3中 B 收到A发送的消息,触发了状态的改变,例如B代表一个银行账户,消息代表取款动作的发生,因此状态改变即更新账户余额,如果需要,B可以给A发送一条回执消息:“已完成状态更新”
现实中,actors A和B可能运行在分布式环境,B可能在另一个机器上无法回应。从一开始,这就提出了关于该做什么的问题;B从A获得消息,完成任务,也许会发送一条回执消息。但这个流程也可能发生故障。


figurep1-4.png

图4 展示了A能够直接向Akka的actor system报告一个请求: “请在未来某个时间点给我发送一个消息“,可以是几毫秒,几秒或者几分钟之后。这个使用的场景是A向B发送消息,得不到回应的情况下,一个超时的消息将会被发送。


figurep1-5.png

在图5中,A获取到超时消息,A处理两种类型的消息:从B得到的回应消息或者超时消息。换句话说,A知道这两种情形下分别该如何处理,这和异常处理不同,大多数异常只是被抛出,而在Akka中,弹性(resilience)是架构中就考虑的特性,而不是事后的想法。

Actor监督 (自修复)

figurep1-6.png

弹性是Akka设计的一部分,让我们来看看Actor的监督机制。Actor能够创建子Actor,形成Actor的层级关系,就像我们在图6中看到的一样。在这个例子中,actor A是监督者,创建了多个干活的actor,他们之间是一种"父-子"关系或者 “监督者-工作者”的关系。

监督者和工作者之间的关系是一种监督策略,当干活的actor处理消息遇到问题的时候,它自己并不处理这个异常,而是由监督者来处理,这种监督策略是定义好的,但也可以定制化。总之,对于工作actor出现的异常,监管actor始终有一个应对计划。

监督者A的响应包括:异常不严重的情况下恢复工作actor,继续执行;或者重启工作actor;或者这个问题实在太严重,需要停止工作actor;最极端的情况是,监督者也无法处理此问题,因此将问题向上报告给它的上级监督者。

因此,根据严重程度,问题可以在层次结构中逐级上升,这都处于开发者的控制之下。要记住的是,这是处理问题的明确方式。

对于actor系统的初学者,往往容易在actor中写入很多的逻辑。随着对actor模型越来越熟悉,会更容易地使用分而治之的策略。

figurep1-7.png

分而治之的目的是为了降低风险,通过构建层次结构的Actor来代理有风险的操作,从而降低影响。

在图1-7中,我们有A1,B1和C3,C3将一些有风险的行为委托给actor D(D3),叶子节点用红色标记这些Actor做的是有风险的操作,例如通过网络和数据库通讯。有风险是因为网络可能中断,数据库可能宕机,或者其他的因素都可能导致错误。

通过将风险的行为推给下层工作的Actor,上层的Actor得到了某种程度的保护。通过Actor的层次结构,工作被委托给更加细粒度的专门的Actor,就像图中把风险行为推给树的叶子节点。

路由和并发

Akka专注于多线程,多核并发,使我们能轻松处理以前需要手工管理多线程的操作。多线程的事情很容易变复杂,所以Akka提供了开箱即用的并发特性,不会遇到Java和Scala中多线程编程的许多技术挑战。


figurep1-8.png

在图1-8中,我们有Actor A和B,以及作为路由的actor R,R创建了一批工作的actor W,A发送消息给路由actor R,要求完成某项工作,R实际并不做这些工作,而是将工作代理给底下的actor W

figurep1-9.png

在图-9中,当actor W在完成A的任务时,这时B发了一个消息给路由actor R,要求完成一些工作。R会转发消息给底下其他的某一个W,这样我们就实现了多线程并发而不用写任何代码。从A和B的视角看,R在同一时刻做了很多工作,但是R在幕后实际上是通过代理工作到许多actor W来实现的。

figurep1-10.png

在图1-10中,我们再来看看这个例子中的Akka监督策略。假设A发送了一个消息给路由R,路由R再转发给实际工作的W,但是W在运行过程中出错了。
在常用的“try-catch”方法编程中,捕获的异常通常是发送给A。然而在actor系统中,是监督者收到这个异常。因此在这个场景中是监督者R收到了异常,而不是A
这就是超时机制起作用的地方了,R发送一个响应给A说:“这里有一些问题,我无法完成你要求的任务”。无论如何,A没有看到异常,作为调用者无需处理问题。而且作为服务的消费者,最好也不是由它来处理,而是由服务的提供者来处理。

Actor模型作为Akka的核心,提供了许多强大的内置特性来管理并发和弹性。它展现了一种不同的思维方式,是一种高效且安全的方法构建分布式系统的方法。

总结:
› Actors 是消息驱动的,有状态的构建模块,模块间异步传递消息。
› 与传统的同步和阻塞不同,Actors 是轻量的,不阻塞线程
› Actor能创建Actor,使用监督层次结构来支持从错误自愈(弹性)。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,529评论 5 475
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,015评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,409评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,385评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,387评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,466评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,880评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,528评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,727评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,528评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,602评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,302评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,873评论 3 306
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,890评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,132评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,777评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,310评论 2 342

推荐阅读更多精彩内容