【问题标题】:Multiple signalR connections/hubs on your website您网站上的多个 signalR 连接/集线器
【发布时间】:2012-08-01 17:21:11
【问题描述】:

如果我有多个页面可以使用多个中心类,那么管理它的最佳方法是什么?

例如:

  • 导航到网站中的另一个页面并基本上“重新打开”与上一页上打开的同一个集线器类的连接是不是很糟糕?

  • 我是否认为在一个页面上打开多个集线器连接是可以的,因为它们都统一在一个连接中,即使它们是不同的集线器类?

【问题讨论】:

  • 我也有同样的情况

标签: c# asp.net signalr


【解决方案1】:

您可以让多个中心在您的网站上共享一个连接。 SignalR 2.0 已更新,可通过一个信号连接处理多个集线器,而不会损失性能。

官方文档:http://www.asp.net/signalr/overview/signalr-20/hubs-api/hubs-api-guide-server#multiplehubs

所有客户端将使用相同的 URL 与您的服务建立 SignalR 连接(“/signalr”或您的自定义 URL,如果您指定了一个),并且该连接用于该服务定义的所有集线器。

与在单个类中定义所有 Hub 功能相比,多个 Hub 没有性能差异

【讨论】:

    【解决方案2】:

    要开始使用集线器,请阅读 WIKI entry for HubsClient Side of Hubs。根据多个页面的上下文,有几件事。

    1. 当您启动一个中心时,它会为您的客户提供一个 ID,该 ID 在多个页面上该中心(有人可以通过示例确认)保持相同。
    2. 重新打开与同一个集线器的连接还不错。您可能在所有页面上运行 hub.start 客户端方法,但是如果它的一个客户端打开多个窗口或从一个页面转到另一个页面,您将在该集线器上具有相同的连接 ID,以便您保持联系。如果它是多个集线器,那么您必须管理集线器以及连接 ID。所以这个问题就像“让多个 ISP 为我的不同网站提供互联网连接服务是不是很糟糕”。你可以拥有它们,但它是一个矫枉过正。一个 ISP 也可以为您提供所有页面。
    3. 单个页面上的多个集线器并不理想,但它会起作用。再次,答案需要一些关于问题的上下文,但通常您可以通过组或使用其他基于参数的方法来区分相同连接 ID 上的各种请求。在同一页面上拥有两个中心可能需要更多资源(需要对此进行测试),而不是使用参数或组来分隔不同的消息传递区域。

    例子:

    您的页面包含两个部分,一个显示实时用户活动的图表和一个以表格形式查看用户所做的实时数据更改的区域。你会创建两个集线器或两个组还是什么?还有其他页面使用相同的图表和数据表。

    我的解决方案:

    1. 我将为应用程序创建一个单一的集线器,以从服务器接收实时数据。
    2. 我将在服务器上创建不同的方法来发送图表点和数据表。
    3. 我将在所有使用这些图表的页面上创建客户端方法,以便与同一集线器上的服务器方法进行通信。

    当您在页面之间切换时,客户端将连接到同一个集线器并请求 getGraph 或 getDataTable 或两者并用相关数据填充其客户端。同样,在服务器上,当数据更改时,您可以调用客户端方法来更新所有客户端或 它们的组(让我们增加这种复杂性)

    假设您有学生和老师查看您的申请。它们需要不同级别的数据访问。您可以使用组在中心上将它们分开,这样您就不会将教师信息发送给学生,也不会将学生数据发送给教师。

    1. 在您的中心加入中,您可以将他们添加到与其角色或任何差异化功能相关联的组中。
    2. 当您发送给所有客户时,现在您可以发送给一组客户,即教师或学生。没有为教师或学生创建另一个中心,他们都在同一个中心。

    回到您的“是否不好”和“还可以”的问题,如果没有实际应用的上下文,这很难确定。除了Performance,我想不出你可以证明多个集线器的合理性。

    【讨论】:

    • 应用程序对不同类型的数据有不同的集线器。我们的应用程序很大,它是关注点的逻辑分离。一些前端客户端只需要实时数据的子集,拥有一个可以连接到的中心而不是管理组是有意义的。
    • 正如@sam 在回答中所建议的那样,您可以这样做,并在此处进行了解释asp.net/signalr/overview/guide-to-the-api/…
    • 我知道,这就是我设置应用程序的方式。我只是在评论,因为你说你想不出一个可以证明多个集线器合理的场景
    • 没问题,我的评论是在 2012 年,当时它无法作为选择。现在是。
    • 您的第二点正是我想要的,多次致电$.connection.hub.start() 也无妨
    【解决方案3】:

    SignalR 核心 - 不可能

    不幸的是,这在 SignalR 的新“核心”版本中不再可能

    https://github.com/aspnet/SignalR/issues/456

    https://github.com/aspnet/SignalR/issues/955


    注意事项:iOS 和自签名证书的问题

    在 iOS 上,每台服务器的连接数限制为四个。

    现在 websockets 没有这个限制(我认为可能是 32 但不确定)。 但是我使用的是自签名证书,它在 Safari 中存在各种问题 - 所以它实际上归结为长轮询(并且这样做并不明显)。

    所以我最终得到了这些联系:

    • 1 - Angular / Webpack 热重载套接字
    • 2 - Web API 调用
    • 3 - 第一集线器
    • 4 - 2 号枢纽
    • 5 - #$$&

    因此,如果我只有三个集线器,整个 Safari 页面就会被蓝色条锁定。甚至 Web API 调用都被阻止了。

    注意:使用 HTTP/2 this limit is gone 但您最好将自己限制在一个集线器,尤其是在您使用热重载的情况下。另外,在开发中设置 HTTP/2 不一定是一件小事。


    那么如何解决呢?

    首先(暂时)将您的集线器设置为仅接受 websocket。这将使您在 Safari 中出现错误(确保错误被​​捕获并显示在警报对话框中)。

    routes.MapHub<SignalRHub>("/rt", options =>
    {
         // when run in debug mode only WebSockets are allowed
         if (Debugger.IsAttached) {
            options.Transports = Microsoft.AspNetCore.Http.Connections.HttpTransportType.WebSockets;
         }
    });
    

    现在您可以确认修复 - 在调试模式下运行,或删除“if”。

    iOS 的问题是即使您接受 https 流量的自签名证书 - 并在浏览器中获得一个漂亮的小“锁定”符号 - 它也不适用于 wss: 协议。所以连接不能升级到 wss,这就是为什么它们最多阻塞 4 个。

    解决方案 #1

    如果您可以将所有内容集中到一个集线器上,那就更容易了 :-)

    我还意识到,如果连接丢失,多个集线器会使重新连接逻辑复杂化。一个集线器只是让这更容易。如果您不小心,您最终会显示 3 个对话框,显示“连接丢失”。重试?'正因为如此,我正在切换到单个集线器。

    虽然我讨厌混合所有内容,但部分类会有所帮助,而且我个人没有太多 SignalR 方法。

    解决方案 #2

    这仅与调试有关,并假设您使用的是自签名的 https 证书。

    改用 letencrypt 之类的东西 - 或 Cloudflare 的 argo 隧道来获取公开信任的证书。这将被 Safari 完全信任,因此您的连接将升级为真正的 Web 套接字。

    解决方案 #3

    创建一个自签名的 ROOT 证书 (CA),然后从中生成带有域名的 SSL 证书。

    这比我想象的要棘手。最后,我发现我的根证书中缺少 Subject Type=CA - 这是 iOS 要求的。如果没有此“扩展”,它会将您的根证书安装为配置文件,但不允许您为 SSL 选择它。

    一旦你安装了根证书,Safari 就可以正常使用 websockets。

    解决方案 #4

    仅使用 http。这对我来说不是一个选项,因为我使用 Facebook / Google / Payment 等某些 API,它们需要 https。

    注意事项

    • 重要提示:现在考虑生产。意识到 websocket 可能由于各种原因不可用,因此如果您在 iOS 上连接了 4 个集线器,这仍然会导致阻塞。你的生活很危险。

    最好首先使用一个集线器。但最好还是正确安装您的证书,以便 iOS 可以与 websockets 一起使用。

    How to create and install X.509 self signed certificates in Windows 10 without user interaction?

    【讨论】:

    • 这让我很不舒服,谢谢。通过“部分类”,我假设您的意思是“公共部分类 MySingleHubForEverything : Microsoft.AspNet.SignalR.Hub”?
    • 完全正确。也许每个方法名称都有一个前缀,例如。聊天发送消息。然后,多人可以更轻松地处理不同的文件,并且感觉不那么混乱。
    • 这整件事是一个糟糕的设计决定。围绕这种设计,部分类是一个杂物,而不是解决方案。这些是非常有限的,因为你不能跨程序集有一个部分类。多亏了这一点,各种架构和代码组织模式和场景都应运而生。例如拥有功能文件夹或功能包,并确保每个功能都定义了自己的集线器功能,不。
    • @DouglasGaskell 我不确定您主要指的是我的设计决策还是 SignalR 设计决策。我开始尝试创建多个集线器,因为它似乎更有意义,但它适得其反。对我来说,部分类是一个完美的设计决定,因为我没有那么多使用 SignalR,我需要继续前进。如果您有一个跨多个“功能包”使用 SignalR 的项目的解决方案,将会有兴趣了解您的想法。
    • 对不起,信号员的决定。就如何使用它而言,它确实使您陷入了困境。多年来一直有人抱怨它,以及从多个集线器、1 个连接移开的决定。基本上能够命名空间和注册函数。
    猜你喜欢
    • 2014-10-03
    • 1970-01-01
    • 2020-01-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-23
    • 1970-01-01
    • 2013-11-24
    相关资源
    最近更新 更多