c# - 构建具有保证消息传递的 SignalR/Knockout 仪表板

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

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

旧概念:

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

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

新概念:

我想在新的仪表板上显示相同的内容,但具有实时更新和“消息”日志。在我们公司,我们大约 90% 的时间都在 MS 堆栈上工作,所以我计划使用 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...   |                
                           +----------------+                
  • 我创建了一个小的“数据丰富应用程序”,它通过 TCP/IP 从监控后端接收事件并向事件添加额外的业务数据(例如,设备的位置、主机名旁边的描述性名称、嗡嗡声- 警报的可读翻译等)不包含在监控系统中。
  • 丰富的事件从应用程序发送到 Redis。我这样做是为了让其他应用程序可以作为订阅者连接到 Redis,因为我在此处输出的数据比监控后端发送的数据更优质且更易读。
  • 目前,对 Redis 的唯一 PUB/SUB 是一个数据库代理,它监听传入事件并将这些事件发送到数据库 (SQL Server),我已经将其用于历史报告目的,但目前仅包含相当简单的数据.

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

问题:

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

但是,如果客户断开连接(例如,在从一个 session 室走到另一个 session 室时他的笔记本电脑处于休眠状态),他会错过来自 SignalR 中心的消息,并且他的仪表板 View 将不再正确!

可能的解决方案是:

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

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

  3. ... ?

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

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

最佳答案

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

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

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

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

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

就是说,如果您想要保证 传送,您将必须确认您的消息并且可能还实现排队机制。默认情况下,SignalR 仅缓冲大约 1000 条消息,然后开始丢弃它们。您可以增加该值,但构建一个根据您的要求量身定制的值可能更有意义。

关于c# - 构建具有保证消息传递的 SignalR/Knockout 仪表板,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29067013/

相关文章:

c# - DbContext 已被释放

c# - 如何停止 "black box"操作?

c# - 使用依赖属性绑定(bind)图像源

c# - 这场比赛的正则表达式

jquery - 使用 jQuery Validate 进行验证并执行 AJAX 调用以返回部分 View

knockout.js - knockout 订阅洞察 : detecting if disposed

knockout.js - 如何将计算的可观察量作为单元格数据放入 Handsontable 中

javascript - 无法使用 Knockout 验证来验证自定义组

c# - Windows Phone 8.1 中 UIElement 的拖放延迟

c# - 允许来自同一电子邮件地址的多个帐户 WEB API ASP.NET IDENTITY