Orleans的源码已经在MIT协议下在GitHub上开源。Microsoft支持资助Orleans和接受社区的贡献。
源码已经在MIT license下开源。
Orlean已经可以用于生产环境,并且已经用于生产环境多年。
有两个角度来回答这个问题,从运行时行为的角度和从建模的角度。
运行时行为的角度:一个对象只有在grain中创建并且不会被远程访问。Grain在系统的任何地方都可以访问并且是透明寻址的,所以开发的时候他们可以自动分配在任何服务器上,并且不受服务器出错或者重启的影响。
建模的角度:在你的和基于Orleans的应用中有四个“东西”:通信接口、消息、grain和grain自己持有的数据。对象可以被用作消息负载和grain自己持有的数据;通信接口是有一些小约束的正常接口。那么什么样的实体应该被建模成grain呢?
一般,你应该使用grain来建模一个有公开暴露的与其他系统组建通信的接口的独立实体并且他有自己的生命——它可以自己独立于其他组建存在。例如,一个社交网络中的用户是一个grain,然而他的名字不是。一个用户新创建一个主页(原文the wall是twitter上类似微博分组微博的东西)可以是一个grain,然后收到的信息列表不是(因为分类主页是其他用户可以访问,但是消息列表是用户自己私有的数据)。希望这些例子可能帮助你分辨出一些模式并且找到与你的业务场景的相似之处。
一个grain的吞吐量受限于一个单线程的激活能执行多少。因此,建议不要升级成单个grain收到不成比例的请求。有许多模式可以帮助避免单个grain的过载,甚至逻辑上这个grain是通信的中心节点的时候。
例如,一个grain是大量周期性的计数器grain和统计grain的聚合器g,一个行之有效的方式的方法是添加一定数量的中间聚合器grain,并且让这上报数据的grain(使用对一个键取模胡总和哈希的方法)报告给中间聚合器,这样负载或多或少的分布到了所有的中间聚合器grain上,并且在中间聚合器的turn中定期地发送部分聚合过的数据给中央聚合grain。
一般没有必要在应用逻辑中强制注销一个grain,因为Orleans运行时自动检测和注销一个闲置的grain激活来回收系统资源。在极少的情况下你认为你需要加快一个grain的注销,grain可以通过调用base.DeactivateOnIdle()方法来实现。
这可以通过使用限定的布局策略,但是我们一般认为这是一种反模式,所以不建议这么做。如果你发现你需要为grain激活指定一个特定的silo,你可能不是按照发挥Orleans的全部优势来设计你的系统的。
按照上面的问题的建议,在没有足够的关于系统的全局状态的信息的情况应用也可以很好的完成系统资源管理的任务。这样在silo重启的情况下特别不利于生产,在云环境中这可能因为系统打补丁而定期发生。因此指定布局可能可能对你的应用的可扩展性和对系统错误的适应性有不利的影响。
一个Orleans部署现在只能在一个数据中心内。
不,现在不能。
Orleans现在不支持在线更新grain的代码。要升级新版的grain代码,你需要准备和启用一个新的部署,切换流量到新部署上,然后关掉旧的不熟。
这可以通过一个storage provider for Azure Cache实现。我不提供,但是你可以很容易地自己写一个你自己的。
Orleans被设计成服务的后端宿主部分并且假设你在你的服务器上创建一个外部客户端连接的前端部分。可以是一个基于http的Web API工程,一个socket放服务器,一个SignalR服务器或者其他你需要的。你的确可以通过互联网连接到Orleans,但是从安全的角度看这不是一个好的实践。
你将会收到一个你能够捕获的一场,并且重试或者其他你的应用逻辑中合理的处理。Orleans运行时不会直接从一个出错的silo上重新创建grain,因为他们中的许多或者全部并不需要立即重新创建。相反的,运行时仅在新的请求到达特定的grain时,个别地重建这样的grain。对于这样的grain,运行时选择一个可用的silo作为新的宿主。这样做的好处是,回复过程只有对于真正在使用的grain进行,并且不是在同一时间,并且发生在所有可用的silo上,这提高了系统的灵敏和恢复速度。 注意在一个silo出错不可用和Orleans集群检测到出错之间是有延迟的。这个延迟可配置的,要平衡检测的速度和误报的可能性在这期间对其grain的所有调用都会失败,但是在失败检测后,有对grain的一个新的调用,grain将会在其他silo上被创建,所以它最终是可用的。更多的信息可以在 这里找到。
由于Orleans使用协调式多工型,它不会自动抢占一个grain的执行,但是Orleans保证对长时间执行的grain调用发出警告,这样开发者能发现他们。协调式多工模型与抢占式多工模型相比有更好的吞吐量。你需要注意grain调用不应该执行任何长时间的任务,比如IO同步并且不要阻塞其他任务的完成。所有等待操作完成都应该使用await关键字或者其他的一部机制。grain应该尽量早的返回好让其他的grain执行来达到最大的吞吐量。
这在正常操作的时候绝不会发生并且每个ID每个grain将有切仅有一个实例。 唯一能发生这种情况的时候是一个silo崩溃了或者他没有被正常关闭而杀死。 在这种情况下,有30-60秒的窗口期(可以设置)一个grain可以存在在不同silo上知道一个被从系统中删除。 从grain Id到他们的激活(实例)地址的映射被存储在一个分布式目录中(用DHT实现)并且每一个silo拥有这个目录的一个分区。当成员观察到两个silo有差异,两个silo都可以请求创建一个实例。结果就是两个grain的实例共存。一旦集群中的silo对成员达成一致,其中一个实例将会被注销并且仅有一个激活存活。 你可以在集群管理页面找到更多关于Orleans如何管理集群的内容。 你也可以可以看一下Orleans的论文了解更多详细信息,然而你不必完全理解就可以写你的应用代码。 你仅仅需要在你写你的应用的时候考虑一个actor有两个实例微小可能性。