关于这个翻译文档的一些说明:
之前逛博客园的时候,看见有个园友在自己的博客上介绍Orleans. 觉得Orleans 是个好东西. 当时心想:如果后面有业务需要的时候可以用用Orleans框架.
当真的有业务需要的时候, 我惊奇的发现很多介绍Orleans框架的人,都只是写了一个入门的示例. 关于Orleans框架的中文资料似乎很少.
直到翻到csdn博客中有个叫闫辉的人有一个系列博客叫《Orleans 2.0 官方文档》, 我非常开心的点了进去,然后我就悲剧的发现这文档几乎是机器翻译, 当然也不是没有收获. 受他的启发,我决定自己来翻译Orleans框架的文档. 当然我的英文还停留在小学的水准, 因此我也是借助机器翻译.所不同的是我会尽量去理解文档的内容, 在我理解的基础上进行翻译.以期能帮到需要了解Orleans框架的园友.
因此翻译的准确度我理解的深浅直接挂钩. 所以如果英文水准高的园友还请移步原版文档( http://dotnet.github.io/orleans/Documentation/index.html) 去看原版文档. 翻译有误的地方也欢迎园友能够指正,在此不胜感激.
概述
Orleans是一个跨平台框架,用于构建强大、可扩展的分布式应用程序.
Orleans基于 .NET 的开发人员工作效率,并将其引入分布式应用程序(如云服务)的世界。奥尔良从单个本地服务器扩展到云中全球分布式、高可用的应用程序。
Orleans采用熟悉的概念,如对象、接口、async/awai和try/catch并扩展至多服务器环境。因此,它可以帮助开发人员将单服务器应用程序向构建弹性、可扩展云服务和其他分布式应用程序扩展。因此,奥尔良通常被称为"分布式 .NET"。
它由 Microsoft Research 创建,并引入了虚参与者(Virtual Actor)模型,作为为云时代构建新一代分布式系统的新方法。Orleans的核心贡献是其编程模型,它驯服了高度并行分布式系统原有的复杂性,同时也不要求开发人员有高超的开发能力.
Grains(颗粒)
所有通过Orleans建立的应用程序的基本单位都是Grains. 也可以理解为任何Orleans程序都是由一个一个的Grain组成的. Grain是一个由用户自定义标识,行为和状态组成的实体. 标识是用户自定义的键(Key),其他应用程序或Grain通过键来调用该Grain. Grains是通过强类型接口(协议)与其他Grains或客户端进行通信. Graint是实现一个或多个这些接口的实例.
Grains 可以在任何存储系统中存储挥发性、持久性状态, 因此,Grains隐式地对应用程序状态进行分区,从而实现自动可伸缩性并简化故障恢复。当Grains处于活动状态时,Grains状态保存在内存中,这样可以降低延迟和数据存储的负载.
Grains的实例化工作由Orleans runtime根据需要自动实现.一段时间不用的Grains将自动从内存中移除以释放资源,这主要是因为Orleans框架允许通过唯一的标识去调用grains(不论这些Grains是否已经加载到内存中去); 同时支持故障自动恢复,因为调用方不需要知道Grains有没有实例化,在哪个服务器上实例化. Grains的生命周期由Orleans运行时进行管理——Orleans运行时负责激活/停用Grains,并会根据需要放置/定位Grains. 开发人员在调用它们的时候就好像它们在内存中一样.
总之, Grains的标识稳定性,有状态性,生命周期受Orleans运行时的管理性,使得基于Orleans框架开发的程序具有可伸缩性,可靠性以及较高性能,同时也不需要开发人员为了系统支持分布式而编写复杂的代码.
示例:物联网后台程序
思考一下这样一个物联网系统的后台程序:程序允许设备接入,然后处理这些数据:过滤、聚合、汇总等;还要支持向设备发送命令. 在Orleans框架下,我们很自然的想到用Grains来对每个设备进行建模. 每一个Grain就像想对应的物理设备的一个双胞胎兄弟一样. Grains将设备最新的数据存放在内存中,以便更快速的查询和处理这些数据,而不需要与物理设备进行直接通信. 通过分析设备时序数据, Grains可以检测设备的状态或条件的变化(例如测量值超过某个阈值)来触发某个特定的动作.
下面是一个简单恒温器的建模:
public interface IThermostat : IGrainWithStringKey
{
Task<List<Command>> OnUpdate(ThermostatStatus update);
}
可以通过调用OnUpdate方法把前端的事件发送给相应的Grain, Grain再根据需要有选择的把命令反馈给物理设备.
var thermostat = client.GetGrain<IThermostat>(id);
return await thermostat.OnUpdate(update);
相同的Grain可以单独实现一个接口,用于控制系统与之交互:
public interface IThermostatControl : IGrainWithStringKey
{
Task<ThermostatStatus> GetStatus();
Task UpdateConfiguration(ThermostatConfiguration config);
}
这两个接口(Ithermostat和IThermostatControl)由一个类来实现:
public
class
ThermostatGrain : Grain, IThermostat, IThermostatControl
{
private ThermostatStatus _status;
private List<Command> _commands;
public Task<List<Command>> OnUpdate(ThermostatStatus status)
{
_status = status;
var result = _commands;
_commands = new List<Command>();
return Task.FromResult(result);
}
public Task<ThermostatStatus> GetStatus() => Task.FromResult(_status);
public Task UpdateConfiguration(ThermostatConfiguration config)
{
_commands.Add(new ConfigUpdateCommand(config));
return Task.CompletedTask;
}
}
以上的Grain类不保存其状态,后续的文档中提供了更详细的状态持久化的示例.
Oreans运行时
Oreans运行时实现了Oreans程序的编程模型. 运行时的主要组件是silo, silo负责托管Grain. 通常, 一组silo是以集群方式运行的, 并以此来实现可伸缩性和容错性. 当这些silo作为集群方式运行的时候,silo之间彼此协调分配工作, 检测故障以及故障恢复. Orleans运行时使得集群中的Grian能够像在一个进程中一样彼此相互通信.
除了核心编程模型之外,silo还为grains提供一组运行时服务,如计时器、提醒(持久计时器)、持久性、事务、流等. 相关的详细信息, 请参阅下面功能部分.
Web以及其他外部客户端通过客户端类库调用集群中的Grains,客户端类库将自动管理网络通信. 当然还有更简单的方式: 客户端与Silo托管到共同的进程中去.
Orleans 兼容 .NET Standard 2.0 及以上版本. 能够在装有.NET Framework(只支持windows) 或.NET Core 的 Windows、Linux 和 macOS上运行.
功能
持久化
Orleans 提供了一个简单的持久化模型, 该模型可以确保处理请求之前Grain是可用 状态的, 并保持一致性. Grain 可以有多个命名持久化数据对象. 例如:把用户配置命名为"Profile";把库存命名为"Inventory"来做持久化. 而这些持久化对象可以保存在任何的存储系统中. 例如:把用户配置(Profile)保存到数据库A, 而库存(Inventory)则保存到数据B. 当Grain运行时,Profile和Invertory都将被加载到内存中去, 这样,在处理里读取请求的时候就不用再去访问存储器. 当Grain的状态被更新时,调用 state.WriteStateAsync() 就可以确保状态的持久性和一致性. 更多详细信息,请参阅Grain持久化的相关文档.
分布式ACID事物
除了上述简单的持久化模型外,Grain还支持有状态事务: 可以把多个Grain放到同一个ACID事务中去,无论这些Grain的状态存储在哪里. Orleans的事务是分散的分布式事务(没有*事务管理器或事物协调器),并且支持序列化隔离. 更多Orleans 事务的详细信息, 请参阅后续文档和微软Resarch技术报告( https://www.microsoft.com/en-us/research/publication/transactions-distributed-actors-cloud-2/).
流
流(或者说流计算)可以帮助开发者近乎实时地去处理连续数据. 流是托管在Orleans框架中的: Grain或客户端发布或订阅流之前,无需创建或注册. 这样使得流的产生者、消费者、基础框架相互之间进行极大险度的解耦. 流处理的可靠性: Grains可以存储检查点(游标). 并可以在激活期间或者之后的任何时间重置已存在的检查点. 流支持向消费者传输批量消息,并以此提高传输效率和恢复性能. 流由排队服务(如:Azure事件总线、Amazon Kinesis等)提供支持, 任意多个流可以多路复用到较少的队列上,并在整个集群中均衡的处理这些数据.
Timers & Reminders(此处本来想翻译提醒的,但感觉怪怪的,索性就不翻译了)
Reminders 和Timer都是Grain的一种调度机制. Reminder主要用于在未来的某个时间点(就算Grain当时没有激活)完成指定的操作(针对Grain被持久化到存储器的情况); 而Timer则是用于处理非可靠的频繁出现的事件(例如某些不重要的通知). 更多Timer 和 Reminders 请参阅后续文档.
灵活的Grain放置
当Orleans激活一个Grain时,Orleans运行时决定在哪个服务器(silo)上进行激活, 这个过程被成为Grain放置. Orleans的放置过程是完全可以灵活配置的, 开发人员可以从一组开箱即用的放置策略中进行选择,可选的选项有:随机,本地优先,基于负载以及自定义逻辑. 这使得Grain的放置非常具有灵活性, 例如: 可以将Grain 放置在靠近需要操作的资源上或者跟它有通信往来的其他Grain服务器上.
Grain 版本控制和异构集群
应用程序的代码都会随着时间或者业务的发展而变化, 如何将这些变化安全快捷地升级到生产系统(这里应该是不停机更新)会面临很大的挑战, 特别是在有状态的系统中. Grain 接口支持版本控制. 集群中维护了一个映射表, 分别记录了在集群中有哪些Grain 可以被哪些Silo所使用, 以及实现的版本. Orleans运行时会结合这个记录信息与Grain放置策略配合使用,以便客户端调用的时候Orleans运行时决定路由到相对应的Grain上. Orleans除了支持Grain版本控制外,还支持异构集群. 不同的Silo可以有不同Grain实现集. 更多相关信息,请参阅 Grain版本控制相关文档.
可伸缩性&容错性
Orleans在设计的时候,就已经充分考虑了系统的可伸缩性. 当有一个新的Silo加入到集群时,Orleans会根据需要去激活它; 当某个Silo由于某个原因(系统规模缩减或节点故障)需要从集群移除的时候,在当前Silo上的Grain会集群的其他Silo上面重新激活. Orleans集群,最小可以缩小到单Silo服务. Orleans支持可伸缩性的同时也支持容错性: Orleans集群会自动检测各个Silo是否故障,并能快速地从故障恢复.
处处运行
Orleans可以运行在任何支持.net core 或 .net Framework的系统上,包括Windows,Linux,macOS,并支持通过K8s部署到docker 等其他物理或虚拟主机上,以及像Azure一样的共有云上的Paas服务.
无状态工作者
Grain可以通过添加一个特殊的标记,使它与其它Grain之间没有任何关联状态. 这样就可以在多个Silo上同时激活, 从而增加无状态操作的并行性. 有关更多信息,请参考无状态工作者Grain的相关文档.
Grain调用过滤器
Grain调用过滤器是指多个Grain之间的公共逻辑. Orleans支持传入和传出调用过滤器. 常见的过滤器用例有: 授权,日志,遥测以及错误处理等.
请求上下文(Request Context)
元数据和其他信息可以使用请求上下文(Request Context)在一些列的请求中传递. 请求上下文(Request Context)可以用来保存分布式跟踪信息或其它用户自定义的值.
开始
请参考入门教程.
编译生成
在Windows系统可以通过运行 build.cmd 脚本在本地生成Nuge包,然后从"/Artifacts/Release/"目录引用所需的Nuget包。接下来就可以运行 test.cmd脚本进行版本验证测试,以及运行 testall.cmd 较本进行功能测试。
在Linux或Mac系统则通过运行 build.sh脚本 或 运行命令 dotnet build ./OrleansCrossPlatform.sln 来生成Orleans。
官方编译
最新的稳定的发布在此处
夜间生成(即每天晚上进行生成)发布到 https://dotnet.myget.org/gallery/orleans-ci 这些生成通过了所有的功能测试,但是没有像发布稳定版本或预发布版本那样进行彻底测试。
在项目中使用夜间生成的Nuget包
若要在项目中使用夜间生成,请使用以下任一方法添加 MyGet 源:
修改 .csproj 文件,在项目文件添加以下节点
<RestoreSources>
$(RestoreSources);
https://dotnet.myget.org/F/orleans-ci/api/v3/index.json;
</RestoreSources>
或者
在解决方案目录下面,创建一个Nuget.Config文件,并添加以下内容
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<clear />
<add
key="orleans-ci"
value="https://dotnet.myget.org/F/orleans-ci/api/v3/index.json" />
<add
key="nuget"
value="https://api.nuget.org/v3/index.json" />
</packageSources>
</configuration>
社区
- 在GitHub 的issue 或 Stack Overflow提题
- Gitter 聊天室
- Orleans 博客
- 在Twwitter 上关注Orleans 账户 @msftorleans (没有微博账号,哈哈哈)
- OrleansContrib – 给Orleans设计各种插件的社区项目。 包含 健康,设计模式,存储提供程序等。
- 为希望改进Orleans而贡献代码的开发人员提供的指南。
- 我们还鼓励您通过GitHub来报告bug 或者在GitHub启动一个新的技术讨论.
授权
这个项目的授权协议是 MIT license.
快捷链接
Orleans 的起源
Orleans是在微软研究部创建的,设计用于云中。自 2011 年以来,它已被多个 Microsoft 产品组广泛用于云和内部办公,其中最引人注目的是游戏工作室,如 343 工业公司和联盟,作为Halo 4和5、Gears of War 4背后的云服务平台。
2015年1月开源以来吸引了许多开发者,他们形成了.NET生态系统中最具活力的开源社区之一。在社区开发人员和微软Orleans团队的积极合作中,每天都会添加和改进特性。微软研究院继续与Orleans团队合作,推出新的主要功能,如地理分布、索引和分布式事务,这些功能正在推动最新技术的发展。对于许多.NET开发人员来说,Orleans已经成为构建分布式系统和云服务的首选框架。