《通过 Actor 模型实现响应式消息处理模式》书评及与 Vaughn Vernon 的问答

阅读数:3804 2016 年 1 月 21 日

在由 Addison-Wesley 所出版的新作《通过 Actor 模型实现响应式消息处理模式》(通过 Actor 模型实现响应式消息处理模式)中,作者 Vaughn Vernon 在全书的开篇部分表述了一个观点:企业级软件开发是一件艰难的工作。他同时强调,这一点并非特指多线程或并发而言,而是一种他所深信的、具有普遍性的观点。之所以企业级软件开发如此困难,是源于开发中所需的所有框架、模式、软件分层、消息系统、应用服务器以及数据库。Vernon 还提到了在他的前一本著作《实现领域驱动设计》 (Implementing Domain-Driven Design)中描述过的端口与适配器架构(Ports and Adapters)(又名多边形架构),他在书中阐述了这种架构能够简化企业级解决方案的原因。但他也表示,即便是对于高级架构师与开发者来说,要充分理解这种架构也需要耗费长达几个月的精力。整个过程中需要考虑到各种因素,并且会出现各种出乎意料的复杂性,他将此称为复杂性栈(complexity stack)。

而与这种复杂性相反,我们在应用程序中真正想要实现的功能无非是将能够表达出用户意图的命令提交至某个领域模型中,并将作为这些命令的结果所创建的领域事件保存起来而已。这是一种简单而强大的模型,Vernon 将其称为简单性栈(simplicity stack)。随后,Vernon 切入了本书的主题 Actor 模型,他在本书的第一章结合响应式软件的原则对 Actor 模型进行了介绍。

Vernon 使用 Scala Akka 代码编写本书的示例,在第二章中,他通过一个简单的指南介绍了 Scala 的基础知识,为本书接下来的示例做好了准备。同样在第二章中,Vernon 也对 Akka 进行了详细的介绍,包括 Actor 的监管、远程调用、集群以及测试,作为进一步学习的基础。

在第三章中,Vernon 着重讲解了性能方面的问题,以及近几十年来出现的 64 位系统、大容量缓存以及多核处理器等技术是怎样使得性能不断提高的。他相信,Actor 模型是一种在企业系统中实现高性能与可伸缩性的重要方法,而 Actor 将帮助开发者克服多线程开发的复杂性,并充分利用先进的多核处理器。

第四章至第十章是全书的重点所在,Vernon 列举了一份包含多种模式的目录,从 Actor 模型的角度描述了在 Gregor Hohpe 与 Bobby Woolf 共同撰写的著作《企业集成模式》(Enterprise Integration Patterns)中所描述的大多数模式。这些章节也涵盖了其他一些相关知识点,包括基本的消息处理模式、基础的通道机制,以及消息的创建、路由和转换。为了简化对Actor 模型图的构建与理解,Vernon 与 Typesafe 合作创建了一系列标准的 Actor 模型元素。读者还可以随意下载本书中的代码示例

在与 InfoQ 进行的一次访谈中,Vernon 分享了他对于 Actor 模型、领域驱动设计、微服务以及 CQRS 的观点。

InfoQ:本书所预期针对的是哪些读者群,他们将从本书中学到哪些内容?

Vaughn Vernon:我编写本书的目的是为处于各种水平的软件开发者提供一种涵盖了入门级乃至高级的指导,使他们了解如何创建下一代软件。这种软件不仅能够实现并发、并行、可伸缩和优秀的性能,同时还具有高度的弹性,并且保证低延迟和高吞吐量的特性。本书完整地阐述了如何创建同时实现了多线程与消息驱动特性的软件,软件团队能够从这部分内容中受益。在我看来,本书的出现是一个有力的宣言,它说明通过 Akka 实现 Actor 模型是在 IT 企业中实现并发性、并行性、大规模性以及高弹性的一种相对较简单的方法。在本书所列举的每一种模式中,详细地说明了如何通过使用这些构建块让团队实现各种高级的应用的系统。本书将这些模式良好地组织在一起,让大多数企业软件的架构师与开发者能够充分地理解,这正是实施 SOA 的正确方式。

InfoQ:你的上一本书是关于领域驱动设计(DDD)的,你能否为我们分享一下从 DDD 迈向 Actor 模型的这段旅程的感受?

Vernon:按我的观点来看,DDD 与 Actor 模型并不存在一种过渡的关系,而是可以同时拥抱这两种技术。我认为 Actor 模型是在当代企业中实现 DDD 的一种自然的方式,我在这本新书中也在不断地强调这一观点。实际上,在适当的时机,我在本书中也会讨论 DDD 的相关话题。如果我认为对于 DDD 的各种主题进行更深入的探讨能够使读者受益,那么我也会不时地引用我的前一本书《实现领域驱动设计》(IDDD)中的内容。在 DDD 的各项主题中,我始终坚持强调一点:DDD 的意义是明确业务领域。而通过 Akka 实现 Actor 模型是描述某个领域模型的最佳方式之一,它不仅能够表现出明确性,并且也可以避免不必要的架构上的困难,以及无意间(或有意识地!)造成的复杂性。对我来说,这段旅程是短暂而甜蜜的。我发现在实践中,Actor 模型与 DDD 是一种完美的结合。

InfoQ:Actor 模型与 Alan Kay 所提出的面向对象的最初想法有多接近?

Vernon:按照 Alan Kay 对于面向对象所预期的工作方式来看,Actor 模型保持了其中大部分的重要元素。他曾表示,与对象内部如何实现相比,对象之间的消息传递是一种更重要得多的关注点。好吧,这基本上就是 Actor 模型的功能了。我有一种感觉:如果 Alan Kay 有机会将他的思想贯彻到底,那么 Smalltalk 语言及环境最终就将完全成为 Actor。这将是一个非常具有竞争力的平台,我认为它将能够承受住几十年的考验。当然,我热爱 Smalltalk 开发原本的形式,我现在也只能够在脑中想象一个结合了 Actor 的 Smalltalk 环境进行编程时的情况。不过,我认为当 Smalltalk 在上世纪 90 年代中叶达到巅峰时,当时的硬件价格以及普及性对于实现这一构想来说仍是无法实现的。而正如当前的现状所见,Scala 与 Akka 构建了一个具备高度生产力的环境,它基本实现了这一构想。尤其是 Scala,它既支持面向对象,并且与 Smalltalk 相比支持更多的函数式编程概念。这是一个具备了令人难以置信的生产力的环境,它令我回想起昔日还在使用 Smalltalk 的美好时光,那是一个纯粹的面向对象编程语言以及开发平台。

InfoQ:CQRS、包括事件溯源在内,他们与 Actor 模型之间存在怎样的关系?

Vernon:Actor 本身就是完美的 DDD 聚合,因为他们本身就是具备原子性的处理单元,可以构成理解的事务边界。因此,至少从战术方法的角度来说,这一特点对于 Actor 模型与 DDD 的结合使用是一个很大的促进。另一个关键点在于 Actor 模型是由消息驱动的,这意味着 Actor 能够很自然地适用于事件驱动的架构。通过事件驱动架构,Actor 能够非常方便地支持事件溯源,某个 Actor 所产生的事件消息将用于构建它的持久状态。不过,对某个事件记录进行查询的做法不太实际,除非你能够将事件投射至某个查询模型中。因此,一旦你使用了事件溯源,这也意味着你需要使用 CQRS 技术,使你能够查询那些向 Actor 发送命令消息后所产生的结果数据。他们之间的结合使用能够产生很好的效果,随着 Akka 的不断成熟,它对于事件溯源和 CQRS 的支持也变得越来越优秀。现如今,可供你选择的工具包括 Akka Persistence 和 Akka Query(这两者都属于 Akka 项目),以及一个名为 Eventuate 的新工具。Eventuate 向使用者做出了许多承诺,而且在短短时间内,它的功能就超越了 Akka Persistence 和 Akka Query。我目前就在一个基于 Scala 和 Akka 的项目中使用了 Eventuate,并且对于它的表现感到相当满意。不管怎样,无论你选择了哪一套工具集,你都会得到足够的功能。

InfoQ:从 DDD 的聚合,或是从微服务的角度来看,Actor 的概念有多大?

Vernon:正如我之前所建议的,一个 Actor 能够完美地扮演 DDD 聚合的角色。我其实很不愿意回答 Actor 模型和微服务的相关问题,因为微服务的概念定义实在是太多了。不过,我还是愿意基于我个人的经验来回答一下这个问题。我认为,微服务在某些情况下可能是一种非常小的概念,因为它倾向于仅提供少量的特性,你可以将其设想为服务端点。(你也可以认为微服务的功能是通过数量有限的 URI 模式提供一定数量的 REST 资源。)在这种情况下,你可能依然需要一打或稍少一些的 Actor 类型去匹配这种级别的微服务,因为这种微服务仍然有一些需要支持的功能。我们刚才已经谈论了 CQRS,从我的经验来看,你需要通过 Actor 支持以下特性:一种聚合类型、一个流程管理器(Process Manager)、视图映射器(View projector,即对新的事件进行响应的 Actor,以保持查询模型的更新)、以及查询服务。这还不包括服务或资源控制器的支持。即使对于某个具备高度关注性的微服务来说,这也将产生 6-10 种 Actor 类型,乃至产生上百万个 Actor 的实例,以领域对象的形式实现各种不同的聚合。

不过从另一方面来看,我认为在某些情况下微服务更接近于 DDD 中的边界上下文的概念。这里我得多说一句,之前我所描述的那种具备极高关注性的微服务或许并不能表述一个完整的边界上下文,它或许仅仅支持某个较大的逻辑边界上下文中有限的一部分内容。不过,我也曾创建过比这更大型的微服务,这些微服务确实能够描述一个完整的边界上下文,在其中可能会包含 5 至 10 种聚合类型。即便如此,微服务也不是一种一体化的架构,因为对于这种级别的微服务,可能需要多达 20 至 25 种 Actor 类型以支持所需的聚合、流程管理器、视图映射器以及查询服务等等。

InfoQ:你认为 Actor 模型有朝一日会成为开发者的主流工具吗?

Vernon:我当然是这样希望的,如若不然,则意味着开发者们还没有理解这一点:他们不能继续停留在以往的那种不具备高伸缩性的企业服务器技术中裹足不前,在今后的几十年中他们必须不断前进。我还想补充一点,我认为 Akka 正在成为主流的技术,从 Akka 用户组中的 Q&A 论坛帖子中的数目就可以看出这一点。总有一些刚接触 Akka 的开发者在询问一些基础的总是,这也说明 Akka 的接收度已经很高。很明显,对于我的新作来说,他们是很好的读者群体。微软也在为 Orleans 项目这个可用的 Actor 模型工具贡献自己的力量,同时在.NET 平台上也出现了 Akka.NET 这样的工具。此外,我还想提一下 Akka Typed,这是一个即将发布的项目,通过它能够设计类型化的 Actor(微软的 Orleans 工具也提供了此类功能),对于那些强类型的支持者来说,该项目将使 Akka 更具吸引力。

关于作者

Vaughn Vernon是人们所公认的软件开发方面的思想领袖,他致力于简化软件的设计与实现,并出版了两本著作《实现领域驱动设计》以及《通过Actor 模型实现响应式消息模式》。他从上世纪80 年代起就开始通过面向对象语言进行编程,从90 年代早期,他在通过Smalltalk 进行领域建模时就大量应用了领域驱动设计中的概念。Vernon 对于分布式计算、消息处理、尤其是Actor 模型非常感兴趣。近几年来,他一直致力于通过领域驱动设计方法应用Actor 模型。

查看英文原文: Reactive Messaging Patterns with the Actor Model Book Review and Q&A with Vaughn Vernon

收藏

评论

微博

发表评论

注册/登录 InfoQ 发表评论