构建SignalR / Knockout仪表板,保证消息传递

时间:2015-03-15 22:36:54

标签: c# asp.net knockout.js signalr real-time

我正在寻找使用实时消息替换我们公司的监控仪表板。

旧概念:

在我们公司,我们有一个仪表板,显示超过700台物理机的(相当详细的)状态,以及添加的元信息。它大约在1.5年前由我的一位同事在ASP.NET Web Forms(我不喜欢)中构建,以使调度员能够协调我们的技术人员应该去哪里解决问题(这些机器位于各种各样的位置)地理位置)。

不幸的是,该应用程序使用30秒的完整页面自动刷新,后面有一个大查询。它很慢,它完全重置你的视图(正如我所说,仪表板包含超过700多台机器)。我个人想改变这个。使用起来非常烦人。我们的调度员已经学会了接受这一点,但我认为他们应该得到更好的待遇。

新概念:

我想在新的信息中心上显示相同的内容,但是有实时更新和"消息"登录。在我们公司,我们在MS堆栈上的工作量约为90%,因此我计划使用ASP.NET MVC,SignalR,SQL Server和Knockout。

我目前拥有什么

看看这个简单的图表:

 +----+ +----+ +----+ +----+ +----+ +----+ +----+            
 | PC | | PC | | PC | | PC | | PC | | PC | | PC | ... ...    
 +--+-+ +--+-+ +-+--+ +--+-+ +--+-+ +--+-+ +--+-+            
    |      |     |       |      |      |      |              
    |   +--+  +--+  +----+    <-+    <-+    <-+              
    |   |     |     |                                        
+---v---v-----v-----v+         +-----------------------+     
|                    | TCP/IP  |                       |     
| Monitoring Backend +--------->  Data Enrichment App  |     
|                    |         |                       |     
+--------------------+         +---------+-------------+     
                                         |                   
          +------------------------------+        +---------+
          |                                       |         |
          |                +----------------+     |         |
    +-----v-----+---------->    DB Proxy    +----->  S Q L  |
    |           | PUB/SUB  +----------------+     |         |
    |   Redis   |                                 |         |
    |           |          +----------------+     +---------+
    +-----------+          |     TO BE...   |                
                           +----------------+                
  • 我创建了一个&#34;数据丰富应用程序&#34;通过TCP / IP从监控后端接收事件,并向事件添加其他业务数据(例如,设备的位置,主机名旁边的描述性名称,警报的可读转换等),即未包含在监测系统中。
  • 已将丰富的事件从应用程序发送到Redis。我这样做是因为其他应用程序可以作为订阅者挂钩到Redis,因为我输出的数据比监控后端发送的数据更优越,更易读。
  • 目前,对Redis唯一的PUB / SUB是一个数据库代理,用于侦听传入事件并将其发送到数据库(SQL Server),我已将其用于历史报告目的,但目前只包含相当简单的数据

这里的想法是在我的ASP.NET应用程序中将SignalR Hub订阅到Redis后端,以将事件发送到客户端。 (那是 TO BE 部分)

问题:

我们的想法是,当客户端导航到仪表板URL时,初始概述将由SQL后端中的状态数据填充。之后,通过SignalR接收事件,并通过更改Knockout属性来更新视图。

但是,如果客户端断开连接(例如,从会议室走到会议室时睡觉他的笔记本电脑),他会错过来自SignalR集线器的消息,并且他的仪表板视图不再正确!

可能的解决方案是:

  1. 在每次事件更改时通过SignalR发送每个设备的完整状态:这是不可能的,因为我必须通过线路发送大量数据。 (我猜测至少有12,000条JSON数据记录)

  2. 在检测到超时连接后强制完全刷新:我不知道如何使用SignalR实现这一点:(

  3. ......?

  4. 处理实时基于推送的数据并保证数据到达的推荐方法是什么?或者我如何处理从超时连接中恢复的问题?或者让这个实时疯狂的想法?

    免责声明:我是系统工程师,而不是专业程序员。这是我的第一个实时网络应用程序。有关SignalR的其他问题通常不会处理大量此类数据。

3 个答案:

答案 0 :(得分:5)

花钱的回答很好,但我想在SignalR的背景下解决方案2;您可以使用SignalR生命周期事件:OnConnectedOnReconnectedOnDisconnected。您可以阅读更多about the events here以及如何use them in a hub here

当客户端首次连接时(OnConnected被调用),您将完全初始化视图。如果客户端暂时失去连接(默认情况下少于30秒,请参阅relevant settings hereOnReconnected被调用),则无需执行任何其他操作;只要标准排队机制中有足够的空间,就会传递排队的消息。

如果客户端PC进入休眠状态,最终会调用OnDisconnected,客户端必须建立新连接。此时,最简单的实现是简单地再次加载所有数据。如果您想重用客户端已有的(过时的)数据,那么您需要

  • 一种检索数据/消息子集的方法(例如,基于序列号或时间戳;由于您已经将事件流存储到数据库中,听起来应该可以集成它)
  • 每当收到消息时,都会在客户端上存储此号码
  • 在建立连接时将其发送到服务器(例如,通过query string),以便服务器可以在OnConnected中读取它并知道是初始化完整视图还是仅初始化变更集

使用SignalR消息进行实时更新应该没问题,但我建议使用常规的MVC / WebAPI控制器来提供初始化视图所需的完整数据集(来自OnConnected)。

也就是说,如果您想要保证投放,您必须确认您的消息,并且可能还要实施排队机制。 SignalR默认只缓存大约1000条消息,然后开始丢弃它们。您可以增加该值,但根据您的要求构建一个可能更有意义。

答案 1 :(得分:5)

SignalR不适用于&#34;可靠消息&#34;。它专为&#34;实时通信&#34;而设计。

问题在于可靠性实际上与实时不兼容。可靠的消息传递意味着消息将至少传送一次。但是,如果数据链接已关闭,则邮件将被延迟传递。但是,实时意味着消息会立即发送,而不会在半小时后发送。

我会切换到&#34; Message Queue&#34;如果可靠性是您所需要的。你会发现他们已经足够快了#34;为了您的目的(RTC通常意味着您需要毫秒范围内的延迟,而MQ应该在第二范围内提供典型延迟)。

您的问题是,如何在SignalR上实现Message Queue。

试试RabbitMQ,我只听说过它的好东西。还有一个Javascript客户端。

答案 2 :(得分:4)

所以,我认为这个问题有点过于宽泛而且没有重点,但我还有更多话要说,而不是评论。

为了保持简单,我不会使用websocket来自己传达消息,而只是作为通知渠道让客户知道有更多数据可用。

首先,我专注于通过标准HTTP通过JSON请求有限的消息集的方法。我假设所有消息都有某种序列号或时间戳,因此已经包含带有戳n的消息的客户端需要能够请求带有戳>n的所有消息。我们称之为消息服务。

现在连接websocket并使用它将简单的“更多可用数据”事件传递给客户端。每次客户端收到事件时,向邮件服务发出一个新请求,要求所有邮件都带有邮票&gt;而不是客户最近的。

如果websocket断开连接,当它重新连接时,向消息服务单独发出请求以确保您处于同步状态,然后再次等待事件,如上所述。