【问题标题】:.Net messaging pub/sub pattern.Net 消息发布/订阅模式
【发布时间】:2016-07-03 12:57:15
【问题描述】:

所以我有一个在 NancyFx 上运行的 .Net 应用程序(需要与平台无关)。 我有一个要求,我需要在某个事件发生时发送通知(订阅)。通知会实现这个接口:

public interface INotification
{
    public void Notify();
}

这将有许多不同的实现,例如电子邮件、Pushbullet、Pushover 等。

我正在努力解决的是如何实际实现这一点,以便INotification 的所有实现在有订阅时都将执行Notify()

谁能指出我正确的方向。

我真的不想使用任何类型的外部队列,因为应用程序将在用户计算机上运行。

所以应用程序是自托管的,客户端和服务器位于用户机器上,它不与外界通信,都是内部的。

【问题讨论】:

    标签: c# .net design-patterns publish-subscribe


    【解决方案1】:

    请稍等一下,我只是想确保我没听错。您还没有写出确切的问题,所以我假设您在某些基础上被困在某个地方。我也会忽略 NancyFX,我不知道,我假设如果它支持这种情况,你会在文档中找到它。

    要让客户知道某些事情发生了变化,您基本上只有 3 个选项:
    (a) 服务器上有一个旧事件列表,服务器会在事件发生时更新它,客户端会定期读取它们并调用执行 Ping 的“通知”!
    (b) 每个客户端打开到服务器的连接并保持打开状态,服务器记住连接,当新的连接发生时,通过已经打开的连接向所有客户端发送消息,客户端获取消息并调用他们的“通知”平吗!
    (c) 客户端向服务器发送注册消息,它包含回调地址/端口/等,服务器存储。当事件发生时,服务器读取列表并将信息发送到这些地址,客户端处理这些请求并根据请求调用它们的通知

    由于您使用“发布-订阅”一词,我假设您的意思是 (C)。

    对于这个选项,关于通知,客户端/服务器的角色实际上是颠倒的。在正常情况下,服务器向客户端公开 API,客户端连接到它,发送请求,服务器处理它并返回一些响应。在这里,双方必须做同样的事情。客户端应用程序还必须向服务器公开一个可调用的 API,以便当“事件”发生时,服务器可以连接到客户端的 API 并向他发送带有通知数据的请求。

    现在,您将如何构建 API - 由您决定。你可以有一个Notify(string xmlizedOrJsonizedData)方法,你可以有参数Notify(string infotype, datetime, data),也可以有很多方法NotifyEmal(...) NotifyBullet(...) ...——在实现注册和订阅记账之后,你只需要服务器调用正确的请求数据到客户端的api,只需就像客户一直在做同样的事情。

    现在编写所有这些内容并重新发明轮子是一项艰巨的工作。有很多图书馆已经可以做到这一点。我看了看,在 NancyFx 文档中没有找到任何关于此的内容。也许您可以使用它来创建客户端 api,就像您创建服务器端 api 一样,但是.. 有一个问题。

    客户端和服务器端不同。

    当客户端与服务器对话时,只有一个服务器可以发送和收听。你可以用幼稚的方式来做,如果你愿意,甚至可以阻止 UI。当服务器发回通知时,可能有 10000 个客户端。您甚至不应该以幼稚的方式开始编写它。循环这么多客户端并等待完成可能会完全冻结您的服务器,如果不冻结,则会导致减速和超时。此外,服务器是公开的。客户不是。客户端通常位于 NAT、防火墙和所有其他有趣的事物后面,这些事物将流量从客户端 -> 传递到 -> 服务器,但可能会阻止另一个方向的流量。最基本的例子是阻塞端口。服务器上的:80 几乎总是通过防火墙,但客户端上的:80 可能不可用,并且当客户端在:23122 上打开它的api 时,它可能不会在他们的防火墙/路由器上配置.. 除非你处理与 upnp/etc.

    这就是为什么选择一个可以为您完成所有这些工作的库是件好事。抱歉,我现在想不起任何名称,请查看 google 的 PublishSubscribe 模式、客户端通知或推送通知服务器端图书馆。

    这就是为什么发明了一种叫做“WebSockets”的东西。这本质上是我在开始时谈到的选项(B)。真的很值得研究。订阅-发布的整个概念也可以通过 websocket 调用/响应服务器/客户端 API/接口来实现,但它可以为您节省大量工作和网络问题。

    我发现了一个可以use Nancy and SignalR 的信息,所以这可能是一个很好的开始。

    【讨论】:

    • 我认为由于我不了解基础知识,我的问题很模糊。我对此表示歉意。当您说客户端和服务器时,客户端和服务器都托管在用户机器内部,它不与外界通信。
    • @JamieR:这很重要,请将其添加到您的问题中,这将有助于其他人以更集中的方式回答。即,这使得(C)在网络问题方面更容易和更安全。它还限制了客户端的数量。这也可能意味着您可能会在没有“订阅数据库”的情况下逃脱。如果客户端数量较少,并且您也不需要可靠的长期订阅,则可以使用非常简单的内存中客户端列表,这将使 (C) 易于实现,甚至可以从头开始手动实现。尽管如此,我还是建议寻找一些图书馆,因为“小型本地系统”喜欢增长。
    【解决方案2】:

    如果侦听器将在同一个应用程序中而不是远程服务中,您可能希望使用应用程序内部的消息总线之类的东西。我知道您可能没有使用 WPF/MVVM,但框架 MVVM light 有一个消息总线的小示例实现。

    但是,出于您的特定目的,您可能希望找到一个不绑定到 MVVM 的示例,或者只是编写类似的东西。

    【讨论】:

    • 你有什么例子,关于如何写类似的东西的建议吗?
    【解决方案3】:

    您可以使用.NET distributed cache as a publisher/subscriber 媒体。 NCache提供了这样的机制

    基本上,您将使用应用程序启动的自定义事件

    注册您的活动

    public void OnApplicationEvent(object notifId, object data)
    {
      ...
    } 
    _cache.CustomEvent += new CustomEventCallback(this.OnApplicationEvent);
    

    并在需要时触发这些事件

    _cache.RaiseCustomEvent("NotificationID", DateTime.Now);
    

    【讨论】:

      猜你喜欢
      • 2016-11-25
      • 1970-01-01
      • 2020-09-21
      • 2021-02-27
      • 1970-01-01
      • 2016-12-14
      • 2015-06-30
      • 2015-03-01
      • 2016-04-18
      相关资源
      最近更新 更多