如何使用 SignalR 从 ASP.NET MVC 3 通知 Web 客户端 MSMQ 任务已完成
Posted
技术标签:
【中文标题】如何使用 SignalR 从 ASP.NET MVC 3 通知 Web 客户端 MSMQ 任务已完成【英文标题】:How to use SignalR to notify web clients from ASP.NET MVC 3 that MSMQ tasks were completed 【发布时间】:2011-12-31 19:22:41 【问题描述】:如何使用 SignalR 在 .NET 4.0 系统中实现通知,该系统由 ASP.NET MVC 3 应用程序(使用表单身份验证)、SQL Server 2008 数据库和 MSMQ WCF 服务(托管在 WAS 中)来处理数据?运行时环境由在 Windows Server 2008 R2 标准版上运行的 IIS 7.5 组成。
我只玩过样本,对 SignalR 的知识并不丰富。
这里有一些背景
Web 应用程序接受来自用户的数据并将其添加到表中。然后它调用 WCF 服务的单向操作(使用数据库键)来处理数据(任务)。 Web 应用程序返回到一个页面,告诉用户数据已提交,处理完成后将通知他们。用户可以查看“索引”页面以查看哪些任务已完成、失败或正在进行中。他们可以继续提交更多的任务(这与之前的数据无关)。他们可以关闭浏览器,稍后再回来。
基于 MSMQ 的 WCF 服务从数据库中读取记录并处理数据。这可能需要几毫秒到几分钟的时间。处理完数据后,记录会更新相应的状态(错误或失败)和结果。
大多数时候,WCF 服务不执行任何处理,但是当它执行时,用户通常希望尽快知道它何时完成。用户仍然会使用 Web 应用程序的其他部分,即使他们没有要由 WCF 服务处理的数据。
这就是我所做的
在主导航栏中,我有一个指示器(类似于 Facebook 或 Google+)供用户在任务状态发生变化时通知他们。当他们点击它时,他们会获得所做工作的摘要,然后可以根据需要查看结果。
使用 jQuery,我轮询服务器以获取更改。控制器操作检查是否有任何进程被修改(完成或失败)并返回它们,否则等待几秒钟并再次检查而不返回客户端。为了避免客户端超时,如果没有更改,它将在 30 秒后返回。 jQuery 脚本等待一段时间并再次尝试。
问题
每个查看页面的用户都会降低性能。他们不需要做任何特别的事情。我们注意到 Firefox 7+ 和 Safari 的内存使用量随着时间的推移而增加。
使用 SignalR
我希望切换到 SignalR 可以减少轮询,从而减少资源需求,特别是如果数据库中的任务方面没有任何改变。我很难让 WCF 服务通知客户端它已完成处理任务,因为它使用基于表单的身份验证。
通过提出这个问题,我希望有人能让我更好地了解他们将如何使用 SignalR 重新设计我的通知方案(如果有的话)。
【问题讨论】:
对this的任何建议 【参考方案1】:如果我理解正确,您需要一种将任务与给定用户/客户相关联的方法,以便您可以在他们的任务完成时告诉客户。
SignalR API 文档告诉我,您可以根据客户端 ID (https://github.com/SignalR/SignalR/wiki/SignalR-Client) 为特定客户端调用 JS 方法。理论上你可以这样做:
-
将 SignalR 使用的客户端 ID 存储为任务元数据的一部分:
正常排队任务。
当任务被处理和出队时:
使用状态更新您的数据库。
使用作为该任务的一部分存储的客户端 ID,使用 SignalR 向该客户端发送通知:
您应该能够检索您的客户端正在使用的连接并向他们发送消息:
string clientId = processedMessage.ClientId //Stored when you originally queued it.
IConnection connection = Connection.GetConnection<ProcessNotificationsConnection>();
connection.Send(clientId, "Your data was processed");
这假设您映射了此连接,并且客户端首先使用该连接来启动数据处理请求。您的“主导航栏”具有启动与您之前映射的 ProcessNotificationsConnection
端点的连接的 JS。
编辑:来自https://github.com/SignalR/SignalR/wiki/Hubs
public class MyHub : Hub
public void Send(string data)
// Invoke a method on the calling client
Caller.addMessage(data);
// Similar to above, the more verbose way
Clients[Context.ClientId].addMessage(data);
// Invoke addMessage on all clients in group foo
Clients["foo"].addMessage(data);
【讨论】:
非 JS 客户端 API 不允许我向特定组或客户端发送消息。结果,将其发送到后台进程没有任何价值。但是,我确实将 id 发送回网站,然后获取“所有者”的“id”并使用该“id”向 SignalR 组发送通知。当用户连接和断开连接时,我将客户端添加到组中。 您的回答有效,但是,最后我决定放弃 SignalR 以获得透明支持安全性的自定义解决方案。因此,用户只能向有权查看此类消息的用户发送通知。该要求从来不是原始问题的一部分,因此我将您的要求标记为答案。 @WernerStrydom 您是选择了不同的库还是从头开始编写所有代码?您能否进一步说明您的最终实现? 我正在使用长轮询。许多浏览器都禁用了 html5 套接字,因此其他机制(例如 flash)有很多限制。 没问题。很好,你做了你的尽职调查。 SignalR 将继续改进,希望您以后可以再次查看它:)。以上是关于如何使用 SignalR 从 ASP.NET MVC 3 通知 Web 客户端 MSMQ 任务已完成的主要内容,如果未能解决你的问题,请参考以下文章
《ASP.NET SignalR系列》第二课 SignalR的使用说明
[Asp.net 开发系列之SignalR篇]专题二:使用SignalR实现酷炫端对端聊天功能
《ASP.NET SignalR系列》第一课 认识SignalR