由 Microsoft 的附属公司 MS Open Tech 开发的 ActorFx 打算提供一个“非规范性的、独立于语言的动态分布式对象模型”。该模型由两个组件构成:actor 本身及其数据存储,它们分别由接口 IActor 和 IActorState 表示。
IActorState 进行状态管理
最初的 IActorState 是一个非常简单的接口,它的本质是一个暴露了 Set、Get、TryGet、Remove 和 Flush 方法的字典。最后一个能够异步运行的操作用于提交改变。按照约定,在调用 commit 方法之后改变会被自动保存到持久化存储,而在此之前则会被存储在一个“本地副作用缓冲区(local side-effect buffer)”中。
这种简化隐藏了一个秘密,那就是可以请求 IActorState 存储任何内容,包括活动代码(Active Code)。
Actor 方法
之前使用 Actor 时必须教导它,让它知道自己能做什么。与传统的.NET 编程不同的是,这并不是通过人工向服务器部署代码来实现的。相反,方法是在运行时使用 IActor.AddAssembly 函数推送到 actor 的。程序集由一个字节数组表示,因此能够通过线路传输并将其存储到 IActorState 自身内部。
这意味着每一个 Actor 都是一个完全封闭的对象。它没有从类或者原型(prototype)中继承方法,它自己本身就有这些方法。同时随时都可以简单地改变这些方法,只要推送一个具有同样名称的新程序集即可。
因为是一次性地加载程序集,所以实际的 Actor 方法需要使用 ActorMethod 属性标记。被该属性标记的方法必须遵循委托模式 Func<IActorState, object[], object>。
向 Actor 发送消息
可以使用 IActor.CallMethod 向一个 Actor 发送消息。IActor.CallMethod 方法有两个参数,一个是方法的名字(来源于之前添加的程序集),另一个是该方法参数的数组。它的返回类型是简单的 System.Object。
通过 IActor.CallMethod 调用方法时,客户端还需要传入客户端 ID 和序列号。这样 Actor 运行时就能识别重复的请求并重新发送之前调用的结果。当然,客户端需要负责确保对于给定的消息这一对值是唯一的。
Actor 之间的通信
Actor 之间通过 IActorProxy 的瞬间实例进行通信。通过代理一个 Actor 能够调用另一个 Actor 的 CallMethod。
除了直接的方法调用之外,还能使用代理设置订阅。基于修改版本的 IObserver,来自于发布 Actor 的事件能够引发对订阅 Actor 方法的调用。调用 Subscribe 方法返回令牌(token)的 Dispose 方法便可以取消订阅。
客户端示例
到现在为止我们谈论的大部分内容都是与 Actor 运行时实现相关的。大多数开发者将会处理 FabricActorClient 这样的客户端。下面我们看看关键的方法:
public class FabricActorClient
{
public FabricActorClient(Uri fabricUri, Uri actorUri, bool useGateway);
public bool AddAssembly(string assemblyName, byte[] assemblyBytes);
public Object CallMethod(string methodName, object[] parameters);
public IDisposable Subscribe(string eventType, IObserver eventObserver);
}
再次强调,必须注意 AddAssembly 会查找匹配 Func<IActorState, object[], object> 签名的静态方法。
ActorFx 基于 Apache 许可,目前处于 alpha 状态,可以从 CodePlex 网站上获取。
评论