Orleans:构建高性能分布式Actor服务
上QQ阅读APP看书,第一时间看更新

第1章 Orleans与Actor编程模型

1.1 什么是Actor编程模型

Actor模型于1973年由Carl Hewitt在论文“A Universal Modular ACTOR Formalism for Artificial Intelligence”中首次提出,最初是面向具有大量处理器的高并发计算机的并行计算模型,其核心思想是将系统中独立的计算过程抽象为Actor(意为执行单元、响应元或激活帧)。如果说计算机程序中面向对象(Object Oriented)的建模方式是将业务实体(Entity)的状态及行为进行聚合,那么Actor模型则是程序运行时的执行逻辑和业务实体状态的聚合模型。

在传统编程模型中,开发人员一般是以服务调用者的角度通过程序对业务数据进行更改,从而完成相应的逻辑操作的;而当多个服务调用者需要在同一时刻对共享数据进行修改时,即会产生数据的并行访问冲突。为了解决冲突,应用程序开发人员需要在应用程序逻辑中显式增加额外逻辑(如使用volatile关键字标注共享变量、使用原子操作或在并发操作前后增加内存屏障等),以保证共享数据的并发读写一致性。这些附加逻辑一方面会给应用程序的执行过程带来额外的性能损耗(CPU缓存同步、线程切换、资源锁竞争等),另一方面也引入了应用逻辑与数据操作的耦合关系,降低了应用程序的可维护性。可以看出,使用上述模型和设计思路构建的应用程序,在高并发场景下很容易由系统内大量的并发冲突而导致运行效率降低。

为了解决此类问题,Actor模型将数据和与其相关的行为逻辑聚合为一个Actor实例(或状态对象):当应用程序需要修改数据时,约定只能通过该数据所属的Actor对象进行操作,并限定每个Actor对象在同一时刻仅响应一个外部调用请求(即Actor实例的内部执行逻辑工作在单线程环境中);当Actor对象同时接收到多个外部调用请求时,将通过一定的规则(通常是先入先出FIFO)对外部请求进行排序并依次执行(见图1-1)。同时,应用程序通过数据对象的ID标识其所属的Actor实例,以区分不同Actor实例内所聚合的状态数据和行为逻辑,并通过该标识访问特定的Actor实例,外部或Actor实例间的逻辑调用通过消息的形式发送至对应Actor实例,调用结果同样以消息的形式返回至调用者。Actor实例可以看作是逻辑可寻址的独立运算及存储单元,使用Actor模型实现的应用程序是由多个Actor实例组成的存储运算阵列,具备了天然的并发调用处理能力。

可以看出,Actor模型在对Actor实例状态数据进行隔离的同时,以单线程语义约束Actor实例对状态数据点操作,并通过Actor间可寻址消息将复杂应用服务场景下的资源竞争转化为消息有序的投递与消费,通过Actor实例级别的有序队列减少了高并发场景下由资源竞争带来的运算性能损耗。因此,Actor模型是一种非阻塞的消息驱动模型,且各Actor实例间的弱耦合性也为应用程序带来了良好的伸缩性,因此非常适用于构建高并发场景下的分布式互联网应用服务。

•图1-1 Actor实例间的消息传递与功能调用

目前,在各种语言平台下已有多种基于Actor模型实现的应用程序开源框架,见表1-1。

表1-1 常见的Actor模型框架