观察者

在某些情况下,简单的消息/响应模式是不够的,客户端需要接收异步通知。例如,用户可能希望在朋友发布新的即时消息时得到通知。

客户端的观察者是一种允许异步通知客户端的机制。观察者是从IGranobserver继承的单向异步接口,它的所有方法都必须是void。grain通过像grain接口方法一样,调用它向观察者发送通知,只不过它没有返回值,因此grain不需要依赖于结果。Orleans运行时会确保单向传递通知。发布此类通知的grain,应该提供一个API来添加或删除观察者。此外,通常也很方便地暴露一个允许取消现有订阅的方法。grain开发者可以使用Orleans ObserverSubscriptionManager<T>泛型类,来简化被观察的grain类型的开发。

要订阅通知,客户端必须首先创建一个实现观察者接口的本地C#对象。然后,它在观察器工厂上调用一个静态方法CreateObjectReference(),将C#对象转换为一个grain引用,然后可以将该grain引用传递给通知grain上的订阅方法。

其他grain也可以使用此模型来接收异步通知。与客户端订阅不同,订阅grain只是将观察者接口实现为门面,并将引用传递给自身(例如this.AsReference<IMyGrainObserverInterface>)。

代码示例

假设我们有一个定期向客户端发送消息的grain。为简单起见,我们示例中的消息将是一个字符串。我们首先在客户端上定义将接收消息的接口。

接口看起来像这样

public interface IChat : IGrainObserver
{void ReceiveMessage(string message);
}

唯一特别的是,接口应该继承IGrainObserver。现在,任何想要观察这些消息的客户端,都应该实现一个类,而该类实现IChat

最简单的情况是这样的:

public class Chat : IChat
{public void ReceiveMessage(string message){Console.WriteLine(message);}
}

现在在服务器上,我们应该有一个grain,它将这些聊天消息发送给客户端。grain还应该有一个机制,让客户端订阅和取消订阅自己来接收通知。对于订阅,grain可以使用工具类ObserverSubscriptionManager。如果您试图订阅已订阅的观察者(或取消订阅一个未订阅的观察者),则此类会抛出一个OrleansException,因此,对此次情况,使用IsSubscribed()方法,或处理OrleansException,就很重要:

class HelloGrain : Grain, IHello
{private ObserverSubscriptionManager<IChat> _subsManager;public override async Task OnActivateAsync(){// We created the utility at activation time._subsManager = new ObserverSubscriptionManager<IChat>();await base.OnActivateAsync();}// Clients call this to subscribe.public Task Subscribe(IChat observer){if (!_subsManager.IsSubscribed(observer)){_subsManager.Subscribe(observer);}return Task.CompletedTask;}//Also clients use this to unsubscribe themselves to no longer receive the messages.public Task UnSubscribe(IChat observer){if (_subsManager.IsSubscribed(observer)){_subsManager.Unsubscribe(observer);}return Task.CompletedTask;}
}

要将消息发送到客户端,可以使用ObserverSubscriptionManager<IChat>实例的Notify方法。该方法接收一个Action<T>方法或lambda表达式(此处TIChat类型)。您可以调用接口上的任何方法将其发送给客户端。在我们的例子中,我们只有一个方法ReceiveMessage,我们在服务器上的发送代码如下所示:

public Task SendUpdateMessage(string message)
{_subsManager.Notify(s => s.ReceiveMessage(message));return Task.CompletedTask;
}

现在,我们的服务器有一个向观察者客户端发送消息的方法,两种方法用于订阅/取消订阅,客户端实现了一个类,以便能够观察grain消息。最后一步是使用我们之前实现的Chat类,在客户端上创建一个观察者引用,并让它在订阅之后接收消息。

代码如下所示:

//First create the grain reference
var friend = GrainClient.GrainFactory.GetGrain<IHello>(0);
Chat c = new Chat();//Create a reference for chat usable for subscribing to the observable grain.
var obj = await GrainClient.GrainFactory.CreateObjectReference<IChat>(c);
//Subscribe the instance to receive messages.
await friend.Subscribe(obj);

现在,只要服务器上的grain调用该SendUpdateMessage方法,所有订阅的客户端都将收到该消息。在我们的客户端代码中,变量c中的Chat实例,将接收消息并将其输出到控制台。

注意:传递给CreateObjectReference的对象是通过一个WeakReference<T>来保存的,因此,如果不存在其他引用,则将被垃圾收集。用户应该为每个不希望被垃圾收集的观察者,保留一个引用。

注意:观察者本质上是不可靠的,因为您不会得到任何响应,来知道消息是被接收和处理,或者由于分布式系统中可能出现的任何情况而导致消息失败。因此,您的观察者应该定期对grain进行轮询,或使用任何其他机制,来确保他们收到了他们应该收到的所有消息。在某些情况下,您可以承受丢失某些消息的代价,并且不需要任何额外的机制,但如果您需要确保所有观察者始终接收消息,并且正在接收所有消息,则定期重新订阅并轮询观察者grain,都有助于确保最终处理所有消息。

Orleans 2.0 官方文档 —— 4.5 Grains - 观察者相关推荐

  1. Orleans 2.0 官方文档 —— 4.1 Grains - 开发一个Grain

    设置 在编写实现grain类的代码之前,请新建一个面向.NET Standard(首选).或.NET Framework 4.6.1或更高版本的类库项目(如果由于依赖性而无法使用.NET Standa ...

  2. Orleans 2.0 官方文档 —— 4.4 Grains - 定时器和提醒器(Reminder)

    定时器和提醒器(Reminder) Orleans运行时提供了两种机制,称为定时器和提醒器,使开发人员能够指定grain的周期性行为. 计时器 定时器说明 定时器用于创建不需要跨越多个激活(grain ...

  3. Orleans 2.0 官方文档中文版 (闫辉)

    目录 第一章 概览 1.1 概览 -> 介绍 1.2 概览 -> 优点 1.3 概览 -> 常见问题 1.4 概览 -> Orleans 2.0 1.5 概览 -> Or ...

  4. Orleans 2.0 官方文档 —— 6.8.4 部署 - 多集群支持 - silo的配置

    Orleans silo的配置 为了快速了解到概貌,我们将在下面的XML语法中,显示所有相关配置参数(包括可选配置参数): <?xml version="1.0" encod ...

  5. Orleans 2.0 官方文档 —— 开发一个Grain

    设置 在编写实现grain类的代码之前,请新建一个面向.NET Standard(首选).或.NET Framework 4.6.1或更高版本的类库项目(如果由于依赖性而无法使用.NET Standa ...

  6. Orleans 2.0 官方文档 —— 3.1 核心概念 - 什么是grain

    什么是grain? grain是Orleans编程模型的关键原语.grain是Orleans应用程序的构建块,它们是隔离的.分布式的.持久性的原子单元.grain是表示应用程序实体的对象.就像在经典的 ...

  7. Orleans 2.0 官方文档 —— 4.8.1 Grains - Grain持久化 - grain持久化的目标

    grain持久化的目标 允许不同的grain类型,使用不同类型的存储提供程序(例如,一个使用Azure表,一个使用ADO.NET),或相同类型的存储提供程序但具有不同的配置(例如,两者都使用Azure ...

  8. Orleans 2.0 官方文档 —— 5.2 集群和客户端 - silo的生命周期

    silo的生命周期 概述 Orleans silo使用可观察的生命周期(参见Orleans Lifecycle),来有序地启动和关闭Orleans系统以及应用程序层组件. 阶段 Orleans Sil ...

  9. Orleans 2.0 官方文档 —— 1.1 概览 - 介绍

    介绍 Orleans是一个框架,它提供了一种简单的方法来构建分布式大规模计算应用程序,而无需学习和应用复杂的并发或其他扩展模式. 背景 云应用程序和服务本质上是并行和分布式的.它们也具有交互性和动态性 ...

最新文章

  1. linux救援模式无法识别分区,Linux操作系统出现严重故障后的救援模式
  2. javaScript的调试(二)
  3. PPF(Point Pair Features)原理及实战技巧
  4. 2021年全球十大工程成就,中国有几个? | 科技袁人
  5. java fft 频谱算法_快速傅里叶变换(FFT)算法原理及代码解析
  6. 几个改变世界的java工具
  7. java 等分切割图片_java 将list按指定大小等分,最后多余的单独一份
  8. transferwise怎么提现_收款工具transfer wise介绍(多币种、可收CJ联盟)
  9. 栈和队列的Java实现
  10. c语言playsound参数,通达信playsound函数
  11. 计算机毕业设计情况进展记录表,南京理工大学泰州科技学院毕业设计(论文)进展情况记录表.doc...
  12. 关于pc端微信登录前后端分离的java后台开发
  13. winEdt下编辑报错:Something‘s wrong--perhaps a missing \item. \end{thebibliography}
  14. 04.ElasticSearch之IK分词器的安装与使用
  15. 计算机无法ping打印机,打印机故障:测试页打印失败是否参阅打印疑难解答已或得帮助...
  16. java:AXIS调用webService接口,返回String类型xml,并用dom4j简单解析xml
  17. 快速通过论文相似度检测
  18. 联想台式机计算机接口,接口篇:四款产品接口配置横向对比_联想ThinkCentre台式电脑_台式电脑评测-中关村在线...
  19. Firebase使用总结(早期)
  20. mysql计算折纸_折纸飞机实验报告.doc

热门文章

  1. 【Vue】9 - 组件(全局、局部)、通信(props、$meit、$refs)、插槽slot、component、$nextTick等
  2. MySQL(InnoDB剖析):24---B+树索引(聚集索引与非聚集索引(辅助索引))、B+树索引的分裂
  3. 多线程【全面学习 图文精讲】
  4. java 替换全角为半角 半角转全角
  5. Flutter 之简洁实用的图片编辑器
  6. GIT的使用总结/GIT如和获取历史版本项目
  7. opencv 内存数据转matlab,OpenCV:IplImage, CvMat, Mat 相互转换
  8. VQA系列论文(五)
  9. ymb是什么缩写_【快看】skr、xswl、zqsg……00后的这些暗语到底是什么意思?
  10. Matlab之Simulink子系统及模块封装