培训
Orleans 的优势
Orleans 的主要优势有:
- 即使对于非专家级的程序员,也能保持较高的开发工作效率。
- 默认透明的可伸缩性,无需程序员付出特殊的努力。
Orleans 编程模型通过提供以下关键抽象、保证和系统服务来提高专家和非专家级程序员的工作效率。
Grains 是 .NET 类,它使用异步方法实现声明的 .NET grain 接口。 因此 Grain 对程序员显示为可以直接调用其方法的远程对象。 这会以透明的方式将方法调用转换为消息、将它们路由到正确终结点、调用目标 grain 的方法并处理故障和个别状况,从而向程序员提供熟悉的 OOP 范式。
运行时保证 grain 每次永远不会在多个线程上执行。 通过结合与其他 grain 的隔离,程序员绝不会在 grain 级别面临并发情况,因此绝不会需要使用锁或其他同步机制来控制对共享数据的访问。 非专家级程序员只需此功能便可方便地控制分布式应用程序的开发。
仅当要处理消息时,运行时才会激活 grain。 这可将创建对 grain 的引用(对应用程序代码可见并受其控制)概念与 grain 在内存中的物理激活(对于应用程序是透明的)完全分隔开来。 在决定何时将 grain“移出页”(取消激活)或“移入页”(激活)方面,这类似于虚拟内存;应用程序可以不间断地访问以逻辑方式创建的 grain 的完整“内存空间”(无论它们在任何特定时间点是否处于物理内存中)。
透明激活可通过在整个硬件资源池中放置和迁移 grain 来实现动态的自适应负载均衡。 此功能对传统执行组件模型做出了重大改进,在此模型中,执行组件的生命周期由应用程序管理。
程序员用于调用 grain 的方法或传递给其他组件的 grain 引用(代理对象)只包含 grain 的逻辑标识。 Orleans 运行时会以透明方式完成 grain 逻辑标识到其物理位置的转换以及对应的消息路由。
应用程序代码与 grain 进行通信时不在意其物理位置,该位置可能由于故障或资源管理原因,或是因为 grain 在调用它时已停用而随时间发生变化。
Orleans 允许将 grain 的内存中状态声明性地映射到持久性存储。 它可同步更新,以透明方式保证调用方仅在持久状态成功更新之后才收到结果。 扩展和/或自定义现有的可用持久性存储提供程序集相当简单。
运行时使用异步和分布式 try/catch 的语义自动在调用链上传播未处理的错误。 因此,错误不会在应用程序中丢失。 这样,程序员就可以将错误处理逻辑放在适当的位置,而无需在每个级别繁琐地手动传播错误。
Orleans 编程模型旨在指导程序员遵循在通过几个数量级缩放应用程序或服务时可能成功的途径。 这通过采用经验证的最佳做法和模式,并提供较低级别系统功能的高效实现来完成。
以下是支持可伸缩性和性能的一些关键因素:
通过使用 grain 作为可直接寻址的实体,程序员可隐式划分其应用程序的整体状态。 虽然 Orleans 编程模型并未规定 grain 应具有的大小,不过在大多数情况下,最好具有相对较大数量的 grain(数以百万计或更多),其中每个参与者都表示应用程序的一个自然实体,如用户帐户或采购订单。
在 grain 可单独寻址并且其物理位置由运行时抽象出来的情况下,Orleans 可非常灵活地采用透明的通用方式进行负载平衡和处理热点,无需应用程序开发人员进行考虑。
grain 在与其他 grain 交互时不会对后者的位置做出任何假设。 由于这种位置透明性,运行时可以动态管理和调整可用硬件资源的分配。 为此,运行时会通过对整个计算群集中的 grain 放置和迁移做出精细的决定,以便对负载和通信模式做出反应 — 而不会使传入的请求失败。 通过创建特定 grain 的多个副本,运行时可以提高 grain 的吞吐量,而无需对应用程序代码进行任何更改。
Orleans 中的 grain 具有逻辑终结点,它们之间的消息传送跨一组固定的全交换物理连接(TCP 套接字)进行多路复用。 这使得运行时能够托管数百万个可寻址实体,并且每个 grain 的操作系统开销很低。 此外,在注册/取消注册物理终结点(例如 TCP 端口或 HTTP URL)甚至关闭 TCP 连接时,激活和取消激活 grain 都不会产生成本。
运行时使用 .NET 线程池计划执行大量单线程粒度,该池针对性能进行了高度优化。 借助采用非阻塞基于延续的样式(Orleans 编程模型的一个要求)编写的 grain 代码,应用程序代码会以非常高效的“协作”多线程方式来运行,没有任何争用。 这允许系统达到较高吞吐量,并以很高稳定性采用非常高的 CPU 使用率(高达 90% 以上)运行。
系统中的 grain 数量增长和负载增大不会形成其他线程或其他操作系统基元这一事实可帮助实现各个节点和整个系统的可伸缩性。
Orleans 编程模型明确了分布式应用程序的异步性质,可指导程序员编写非阻塞异步代码。 与异步消息传递和高效计划相结合,这可实现高度的分布式并行性和整体吞吐量,而无需显式使用多线程。