让我们来看看在.NET生态系统中我们有哪些工具可以使用。在接下来的几节中,我们将介绍流行的框架选择。Orleans, Proto.Actor, Akka.Net, 和Dapr。我们将重点介绍它们的独特功能和方法。
Orleans Orleans框架是虚拟actor模型的前身。它来自于2010年开始的一个微软研究项目。它为《光环4》等知名游戏的后台服务提供了支持。当它开始的时候,它的边缘有点粗糙,有静态类,大量的反射,XML配置等等。然而现在,经过几次迭代后,它的使用已经相当愉快了。
Orleans只关注虚拟行为体模型--传统的行为体层次结构不被明确支持。
Orleans实现了自己的集群机制,并依靠外部数据库为集群成员提供成员信息。Orleans也有自己的代码生成的串行器用于远程信息传递(尽管串行器是可插拔的)。同样,网络协议也是奥尔良特有的。
优点
- 成熟的开源项目,得到微软的支持
- 全面的文档
- 庞大而活跃的社区
- 支持actor之间的pub-sub流
- 持久性的提醒--即使行为者已经停用,计时器也能发挥作用
- 流行数据库的成员表实现,例如社区提供的Mongo DB。同样地,许多持久化的实现也是可用的。
- Orleans Dashboard是一个很好的补充,可以快速窥视集群的运行情况
- 分布式ACID事务--如果你真的需要的话(我们自己还没试过这个功能)。
缺点
- 没有明确地支持传统的行为体层次结构
- 没有可用的商业支持
- 对于我们的口味来说,"通过属性进行配置 "和其他自动魔法还是有点太多了
Akka.Net Akka.Net是来自Java生态系统的Akka项目的一个移植。它是.NET基金会下的一个项目,由Petabridge公司支持。它有一个开源的核心和作为商业插件提供的工具和服务。
为另一个框架的近似移植,Akka.Net带来了原版的所有好主意,但也带来了有争议的设计决定(例如HOCON配置)。
Akka.Net主要集中在传统角色和监督层次的使用案例上。但它也有集群模块,可以跨多台机器创建角色系统。特别是,集群分片机制类似于虚拟行为体的方法。从用户的角度来看,主要的区别是Akka.Net不处理单一的虚拟角色。它而是根据用户指定的分片策略将它们分组为分片,然后将这些分片分配给集群中的机器。它在这方面有一些独特的解决方案,这将在另一篇博文中讨论。
Akka.Net遵循的路线是实现自己的集群机制以及网络协议和序列化(可以交换实现)。虽然开箱即用的1.4版本使用了Newtonsoft JSON序列化器,但我们的测试表明,使用Hyperion序列化器(目前正在测试)可以获得更好的性能。
优点
- 有公司支持,有商业支持计划
- 全面的文档和大量的例子和视频资料
- 基于著名的Akka框架的概念
- 能够将集群与本地监督层次结合起来
- 集群自动负载平衡和 "记忆实体 "机制
缺点
- HOCON配置和其他一些从Akka导入的怪异现象
- 一些必要的组件需要购买许可证,比如监控库Phobos
- 专注于传统的行为者模型
- 集群是基于种子节点的,这需要一些集群节点有稳定的网络地址。建议使用Lighthouse服务,例如将其作为Kubernetes中的一个有状态的集合部署。
Proto.Actor Proto.Actor是由Akka.Net的创建者创建的一个框架。它吸收了Akka.Net的经验,但同时也将 "不要重新发明轮子 "作为其主要理念。
这意味着像序列化、消息传递和集群等方面都重复使用了现有的和经过战斗检验的解决方案。特别是,Proto.Actor使用了带有protobuf的gRPC。它还使用现有的集群提供者,如Consul、Zookeeper,甚至是原生的Kubernetes APIs。你可以选择适合你的用例和基础设施的实现。
虚拟actor是Proto.Actor中的第一类概念。该框架有很多方式支持这种编程模型,包括代码生成的基类,这些基类封装了低层次的通信问题。同时,也可以创建传统的监督层次。这些方法在Proto.Actor中很容易混合和匹配。
Proto.Actor还提供了一个有趣的机制,叫做Local Affinity,我们将在后面的博文中探讨。另一个区别在于该框架的Go版本。
优点
- 使用众所周知和经过测试的通信和集群标准
- 能够将聚类与本地监督层级相结合
- 在我们的ping-pong基准中具有最高的消息吞吐量
- 近几个月来,文档得到了许多改进
- 在集群中分布和定位行为者的各种选项(分区身份查询、分区激活器查询、数据库查询)
- 本地亲和力机制
- 在我们的主观意见中,最好的编程API
- 兼容OpenTelemetry的监控
缺点
- 没有可用的商业支持
- 仍未达到1.0版本,导致偶尔会出现一些破坏性的API变化
- 社区相对较小
- 关注事件来源的持久性,这在很多情况下是不相关的。幸运的是,提供你自己的持久化实现很容易。
Dapr Dapr是另一个由微软支持的开源项目。它是一个更广泛的框架,提供服务发现、服务间安全可靠的通信以及存储和pub-sub功能的抽象。但Dapr的一个额外的部分是虚拟角色模型的实现,其中有一些从奥尔良借来的概念。
Dapr以一种与技术无关的方式实现其功能。该框架本身是用Go编写的,但它运行在实际应用的旁边(例如在sidecar容器中),并通过HTTP或gRPC调用与之进行通信。这很有趣,因为你可以用任何技术建立一个基于行为体的解决方案。然而,Dapr运行时并没有照顾到一个关键的方面--角色的状态。行为体应该把它的状态保存在内存中,只有在需要时才与持久化存储进行交互。如果你使用Dapr SDK之一,状态会被缓存在内存中,否则你必须自己实现一个类似的解决方案。
缺点是,边车的方法会引入开销。看起来,Dapr的虚拟演员实现并不是为了高吞吐量的场景。
展示的应用程序,eShopOnDapr,使用虚拟角色来实现一个持久的工作流(流程管理器模式),这是一个有趣的用例。
优点
- 由微软支持的项目
- 使用Dapr开始工作相对容易
- 技术不可知(尽管使用其中一个SDK会使你的生活更容易)。
- 如果你已经使用了Dapr,就很方便
- 持久性的提醒--即使行为者已被停用,计时器也能工作。
缺点
- sidecar和应用程序之间的HTTP通信的开销。
- 没有明确支持传统的角色层次结构
- 复杂的部署结构,需要多个组件,例如在Kubernetes中运行,包括用于配置的CRD。
- 需要在开发机器上使用Dapr运行时间