目录
- 为什么我们用 Orleans
- Dapr VS Orleans
- Actor 模型
- Orleans 的核心概念
为什么我们用 Orleans
- 分布式系统开发、测试的难度(服务发现、通信)
- 运维的复杂度(伸缩性与可靠性的保障)
- actor 拥有全局唯一身份
- 自动伸缩功能
Dapr VS Orleans
Dapr 文档:https://docs.dapr.io
Orleans 文档:https://learn.microsoft.com/zh-cn/dotnet/orleans
Dapr | Orleans |
runtime 运行时 | framework 框架 |
actor 只是其中的一个组件 | actor + state |
无分布式事务方案 | 提供最终一致性保障 |
依赖于 dapr 运行时 | 无除了 .net 环境的依赖 |
比较难进行 debug | 调试开发无差别 |
docker 与 k8s 支持 | 裸金属/docker/k8s 支持 |
多种语言 sdk 支持 | 仅 C# 语言 |
1.8 版本 | 3.6 版本,4.0 即将发布 |
Actor 模型
- 对同一个 actor 的调用按顺序执行
- one actor 可以创建其他的 actor
- 给一个 actor 发消息(调用它的执行方法)
- 不能自己去实例化和销毁
- 同一个 identity 的 grain 在系统内只存在一共激活的实例
- actor 没有共享数据
- actor 的数据不可用被外部直接修改
我们有个工作 jd001,就是一个 actor,它会有一个 internal state,状态里面会有一个 identity,它是唯一的,不可改变的
有一个浏览工作的消息,它把工作的 id,以及当前的浏览者信息传入进来,调用 jd001
jd001 会创建一个 activity actor ac001,然后调用 ac001 把浏览记录下来,有一个活动类型 view
Orleans 的核心概念
- 单线程执行模型
- 多路通信复用
- 其他优势
- Grain
- 集群
- 最佳实践
单线程执行模型
actor 在 Orlean 中叫作 grain 谷仓
运行时保证 grain 每次永远不会在多个线程上执行,通过结合与其他 grain 的隔离,程序员绝不会在 grain 级别面临并发情况,因此绝不会需要使用锁或者其他同步机制来控制对共享数据的访问,非专家级程序员只需此功能便可方便地控制分布式应用程序的开发
多路通信复用
Orlean 中的 grain 具有逻辑终结点,它们之间的消息传送跨一组固定的全交换物理连接(TCP 套接字)进行多路复用,这使得运行时能够托管数百万个可寻址实体,并且每个 grain 的操作系统开销很低,此外,在注册/取消注册物理终结点(例如 TCP 端口或 HTTP URL)甚至关闭 TCP 连接时,激活和取消激活 grain 都不会产生成本
其他优势
- 熟悉的面向对象的编程(OOP)范式(grain 即是 .net 类)
- 激活透明
- 位置透明
- 自动传播错误
- 自适应资源管理
高性能
- 显示异步
- 多路复用通信
- 高效计划:运行时在自定义线程池中计划大量单线程 grain 的执行(每个物理处理器核心一个线程),借助采用非阻塞基于延续的样式(Orleans 编程模型的一个要求)编写的 grain 代码,应用程序代码会以非常高效的“协作”多线程方式来运行,没有任何争用,这允许系统达到较高吞吐量,并以很高稳定性采用非常高的 CPU 使用率(高达 90% 以上)运行。
Grain
- 概念
- 模式
- 持久化
- 特点
- 计时器和提醒
概念
grain = identity + behavior [ + state ]
- identity : User/davidgri
- behavior : class User : Grain, Iuser
- state : in-memory, persisted, or stateless
模式
- silo 内模式(集群内)
- silo 外 client-server 模式(集群外:客户端、服务端不在同一个 host 里面)
持久化
激活 grain 时,会自动读取 grain 状态,但 grain 需要负责在必要时显示触发任何已更改的 grain 状态的写入
IPersistentState<TState>
Grain<TState>
(已过时)
通过 MongoDB 持久化
Orleans.Providers.MongoDB: https://github.com/OrleansContrib/Orleans.Providers.MongoDB
特点
- Grain 类似于对象,但是,它们是分布式的,虚拟的并且异步的
- 它们是松散耦合、隔离并且基本上独立的
- 避免在 grain 之间进行琐碎通信
- 直接使用内存比传递消息的开销要小得多
- 将过于琐碎的 grain 组合成单个 grain 可能更好
- 需要考虑参数和序列化的复杂性/大小
- 反序列化两次可能比重新发送二进制消息的开销更大
- 避免瓶颈 grain
计时器和提醒
Timer && Reminder:https://learn.microsoft.com/zh-cn/dotnet/orleans/grains/timers-and-reminders
集群
Orleans silo 生命周期概述:https://learn.microsoft.com/zh-cn/dotnet/orleans/host/silo-lifecycle
Kubernetes 托管:https://learn.microsoft.com/zh-cn/dotnet/orleans/deployment/kubernetes
最佳实践
哪些应用适合采用 Orleans
- 有大量(数百、数百万、数十亿甚至数万亿)松散耦合的实体
- 实体足够小、可以是单线程实体
- 工作负载是交互式的
- 预期或可能需要多台服务器
- 不需要全局协调、或者每次只需在少量几个实体之间进行小规模协调
哪些不适合
- 必须在实体之间共享内存
- 少量的大实体可以是多线程实体
- 需要全局协调和/或一致性
- 长时间运行的操作