简体   繁体   English

.Net消息传递pub / sub模式

[英].Net messaging pub/sub pattern

So I have an .Net application that is running on NancyFx (needs to be platform agnostic). 所以我有一个在NancyFx上运行的.Net应用程序(需要与平台无关)。 I have a requirement that I need to send a notification when a certain event happens (subscription). 我要求在某个事件发生时(订阅)我需要发送通知。 The notification will implement this interface: 通知将实现此接口:

public interface INotification
{
    public void Notify();
}

There will be many different implementations for this eg Email, Pushbullet, Pushover etc. 这将有许多不同的实现,例如Email,Pushbullet,Pushover等。

What I am struggling with is how to actually implement this so that all implementations of INotification will execute Notify() when there is a subscription. 我正在努力的是如何实际实现这一点,以便所有实现的INotification将在订阅时执行Notify()

Can anyone point me in the right direction. 任何人都可以指出我正确的方向。

I don't really want to use any sort of external queues, since the application will be running on the users machines. 我真的不想使用任何类型的外部队列,因为应用程序将在用户计算机上运行。

So the application is a self-hosted, the client and the server are located on the users machine and it does not talk to the outside world, it's all internal. 因此,应用程序是自托管的,客户端和服务器位于用户计算机上,它不与外界通信,它都是内部的。

Excuse me for a second, I'll just want to make sure I got you right. 对不起,我只想确保我找对你。 You have not written what's the exact problem, so I assume you are stuck somewhere at some basics. 你还没有写出确切的问题,所以我假设你被某些基础知识所困扰。 I'll also ignore NancyFX, I don't know it, I assume that if it supported this case, you'd find it in docs. 我也会忽略NancyFX,我不知道,我认为如果它支持这种情况,你会在docs中找到它。

To let the client know that something has changed, you essentially have only 3 options: 为了让客户知道某些事情发生了变化,您基本上只有3个选项:
(a) there's a list of old events on the server, server updates it when events happen, clients periodically read them and invoke their 'Notify' that does Ping! (a)服务器上有一个旧事件列表,服务器在事件发生时更新它,客户端定期读取它们并调用它们执行Ping的“通知”!
(b) each client opens a connection to the server and keeps it open, server remembers the connections and when a new even happens, sends a message to all clients over already-opened connections, clients get the message and invoke their 'Notify' that does Ping! (b)每个客户端打开与服务器的连接并保持打开状态,服务器记住连接,当新的连接发生时,通过已打开的连接向所有客户端发送消息,客户端获取消息并调用他们的“通知” Ping!
(c) clients send registration message to the server, it contains callback address/port/etc, server stores that. (c)客户端向服务器发送注册消息,它包含回调地址/端口/等,服务器存储。 when event occurs, server reads the list and sends infos to these addresses, clients handle these requests and call their Notify according to the request 当事件发生时,服务器读取列表并向这些地址发送信息,客户端处理这些请求并根据请求调用它们的Notify

Since you use words 'publish-subscribe', I assume you meant (C). 由于您使用“发布 - 订阅”字样,我认为您的意思是(C)。

For this option, regarding notifications, the roles of client/server are actually reversed . 对于此选项,关于通知,客户端/服务器的角色实际上是相反的 In a normal case, the server exposes API to client, client connects to it, sends a request, server handles it and returns some response. 在正常情况下,服务器向客户端公开API,客户端连接到它,发送请求,服务器处理它并返回一些响应。 Here, both sides must do the same. 在这方面,双方必须这样做。 The client app must also expose a callable API to the server, so that when "event" occurs, the server can connect to the client's API and send him a request with notification data. 客户端应用程序还必须向服务器公开可调用的API,以便在“事件”发生时,服务器可以连接到客户端的API并向他发送包含通知数据的请求。

Now, how you'd structure the API - it's up to you. 现在,您如何构建API - 这取决于您。 You can have one Notify(string xmlizedOrJsonizedData) method, you can have parameters Notify(string infotype, datetime, data) , or many methods NotifyEmal(...) NotifyBullet(...) ... - after implementing the registration and subscription bookkeeping, you will just need the server to call into the client's api with correct request data, just like the client does the same all the time. 你可以有一个Notify(string xmlizedOrJsonizedData)方法,你可以有参数Notify(string infotype, datetime, data) ,或许多方法NotifyEmal(...) NotifyBullet(...) ... - 实现注册和订阅后簿记,你只需要服务器用正确的请求数据调用客户端的api,就像客户端一直这样做一样。

Now that's a bit of work to write all of that and reinvent the wheel. 现在,编写所有这些并重新发明轮子是一项工作。 There are lots of libraries that already can do it. 有很多库已经可以做到了。 I looked and I didn't find anything in NancyFx docs about that. 我看了,我没有在NancyFx文档中找到任何关于它的内容。 Probably you could use it to create a client-side api, just like you create server-side api, but .. there's a catch. 可能你可以用它来创建一个客户端api,就像你创建服务器端api一样,但是......有一个问题。

Client-side and server-side differ. 客户端和服务器端不同。

When client talks to sever, there is only one server to send to and to listen to. 当客户端与服务器通信时,只有一个服务器要发送和收听。 You can do it in naive way, even blocking the UI if you like. 您可以以天真的方式进行,甚至可以阻止UI。 When server sends notifications back, there can be 10000s of clients. 当服务器发回通知时,可能有10000个客户端。 You should not even start writing it in a naive way. 你甚至不应该以天真的方式开始写它。 Looping over that many clients and waiting till finished can freeze your server completely, and if not freeze, then cause slowdowns and timeouts. 循环使用那么多客户端并等到完成后可以完全冻结您的服务器,如果没有冻结,则会导致速度减慢和超时。 Furthermore, server is out there in public. 此外,服务器在公共场所。 Clients are not. 客户不是。 Clients often are behind NATs, firewalls, and all other funny things that pass traffic from Client->to->Server but may block traffic in the other direction. 客户端通常位于NAT,防火墙以及所有其他有趣的事物之后,这些事物将流量从Client->传递到 - > Server,但可能会阻止其他方向的流量。 Most basic example is blocking ports. 最基本的例子是阻塞端口。 :80 on the server is almost always passed through firewalls, but :80 on client will be probably unavailable and when client opens its api on :23122 it probably won't be configured on their firewalls/routers .. unless you handle that with upnp/etc. :80服务器上的:80几乎总是通过防火墙,但是:80客户端上的:80可能不可用,当客户端打开它的api时:23122它可能不会在防火墙/路由器上配置..除非你用upnp处理它/等等。

That's why it's good to pick a library that can do all of that for you.. Sorry, I can't recall any name now, check ie google for PublishSubscribe pattern, or client-notification or push-notification server-side library. 这就是为什么选择一个可以为你完成所有这些工作的库是很好的。抱歉,我现在不记得任何名字,检查谷歌的PublishSubscribe模式,或客户端通知或推送通知服务器端库。

That's why a thing called "WebSockets" was invented. 这就是为什么发明了一种叫做“WebSockets”的东西。 That's essentially option (B) I talked about in the beginning. 这基本上是我在开始时谈到的选项(B)。 It's really worth investigating. 这真的值得研究。 The whole concept of subscribe-publish is also implementable as calls/responses to server/client apis/interfaces over websocket, but it saves you a lot of work and network problems. 订阅发布的整个概念也可以通过websocket实现对服务器/客户端api /接口的调用/响应,但它可以为您节省大量的工作和网络问题。

I've found an info that it's possible to use Nancy and SignalR so that may be a very good start. 我发现了一个可以使用Nancy和SignalR的信息,这可能是一个非常好的开始。

If the listeners are going to be in the same application and not a remote service, you probably want to use something like a messagebus internal to the application. 如果监听器将在同一个应用程序而不是远程服务中,您可能希望使用类似于应用程序内部的消息总线。 I know you may not be using WPF/MVVM but the framework MVVM light has a small example implementation of a message bus. 我知道您可能没有使用WPF / MVVM,但框架MVVM light有一个消息总线的小示例实现。

However for your particular purpose you may want to find an example that is not tied into MVVM or just write something similar. 但是,出于特定目的,您可能希望找到一个与MVVM无关或仅编写类似内容的示例。

You could use a .NET distributed cache as a publisher/subscriber medium. 您可以使用.NET分布式缓存作为发布者/订阅者媒体。 NCache provides such a mechanism NCache提供了这样一种机制

Basically you'll be using the Application Initiated Custom Events 基本上您将使用应用程序启动的自定义事件

Register your events 注册您的活动

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

And fire those events whenever you need to 并在需要时发射这些事件

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM