C# 您网站上的多个 signalR 连接/集线器

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11764360/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-09 19:08:25  来源:igfitidea点击:

Multiple signalR connections/hubs on your website

c#asp.netsignalr

提问by anthonypliu

If I have multiple pages that could use multiple hub classes, what is the best way to manage this?

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

For instance:

例如:

  • Is it bad to navigate to another page in the website and essentially "reopen" the connection to the same hub class that was open on the previous page?

  • Am I correct in thinking that opening multiple hub connections on a page is ok because they are all unified in one connection, even if they are different hub classes?

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

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

回答by Farrukh Subhani

To start with Hubs read the WIKI entry for Hubsand Client Side of Hubs. There are couple of things according to the context of a multiple pages.

要开始使用集线器,请阅读集线器集线器客户端WIKI 条目。根据多个页面的上下文,有几件事。

  1. When you start a hub it gives your client an ID which stays the same for that hub(someone can confirm with example) over multiple pages.
  2. Its not bad to reopen the connection to the same hub. You might have hub.start client side method running on all pages however if its one client opening multiple windows or going from one page to another you will have same connection ID on that hub so you can keep in contact. If it was multiple hubs then you have to manage hubs as well as connection IDs. So this question is like "Is it bad to have multiple ISPs serving my internet connection for different websites". You can have them but it is an overkill. A single ISP can server all pages to you as well.
  3. Multiple hubs on a single page is not ideal but it will work. Again the answer need a bit of context to the problem but in general you can differentiate between various requests on same connection ID via groups or using other parameter based approach. Having two hubs on same page may take more resources(need to test this) than using parameters or groups to separate different areas of messaging.
  1. 当您启动一个集线器时,它会为您的客户提供一个 ID,该 ID在多个页面上与该集线器保持相同(有人可以通过示例进行确认)。
  2. 重新打开与同一个集线器的连接也不错。您可能会在所有页面上运行 hub.start 客户端方法,但是如果它的一个客户端打开多个窗口或从一个页面转到另一个页面,您将在该集线器上拥有相同的连接 ID,以便您可以保持联系。如果是多个集线器,则您必须管理集线器和连接 ID。所以这个问题就像“让多个 ISP 为不同网站的互联网连接提供服务是不是很糟糕”。你可以拥有它们,但这是一种矫枉过正。单个 ISP 也可以为您提供所有页面的服务。
  3. 单个页面上的多个集线器并不理想,但它会起作用。同样,答案需要一些问题的上下文,但通常您可以通过组或使用其他基于参数的方法来区分对同一连接 ID 的各种请求。与使用参数或组来分隔不同的消息传递区域相比,在同一页面上拥有两个集线器可能会占用更多资源(需要对此进行测试)。

Example:

例子:

You have a page that has two parts, a graph which shows real time user activity and an area to see real time data changes done by users as a table. Will you create two hubs or two groups or what? There are other pages which use same graph and data table.

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

My Solution:

我的解决方案:

  1. I will create a single hub for the application to recieve real time data from the server.
  2. I will create different methods on server to send graph points and data tables.
  3. I will create client side method on all pages that use these graphs to communicate with server methods on the same hub.
  1. 我将为应用程序创建一个集线器以从服务器接收实时数据。
  2. 我将在服务器上创建不同的方法来发送图形点和数据表。
  3. 我将在所有使用这些图与同一集线器上的服务器方法进行通信的页面上创建客户端方法。

When you switch between pages the client will connect with same hub and request getGraph or getDataTable or both and populate its client with relevant data. Similarly on server when data changes you can call client side method to update all clients or group of them(lets add this complexity)

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

Assume you have students and teachers looking at your application. They require different level of data access. You can use groups to keep them separate on the hub so you are not sending teachers info to students and students data to teachers.

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

  1. On your hub join you can add them to join a group associated with their role or any differentiating function.
  2. When you send to all clients , now you can send to group of clients that is teachers or students. Not creating another hub for teachers or students, they are all on same hub.
  1. 在您的中心加入时,您可以将他们添加到与他们的角色或任何差异化功能相关联的组中。
  2. 当您发送给所有客户时,现在您可以发送给教师或学生的客户群。不是为教师或学生创建另一个中心,他们都在同一个中心。

Coming back to your question of "is it bad" and "is ok" this is difficult to establish without context of actual application. I cant think of a scenario where you can justify multiple hubs apart from Performance.

回到你的“它是坏的”和“好的”的问题,如果没有实际应用的背景,这是很难建立的。我想不出一个场景,除了Performance之外,您还可以证明多个集线器是合理的。

回答by Sam

You can have multiple hubs sharing one connection on your site. SignalR 2.0 was updated to handle multiple hubs over one signlar connection with no lost in performance.

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

Official docs: http://www.asp.net/signalr/overview/signalr-20/hubs-api/hubs-api-guide-server#multiplehubs

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

All clients will use the same URL to establish a SignalR connection with your service ("/signalr" or your custom URL if you specified one), and that connection is used for all Hubs defined by the service.

There is no performance difference for multiple Hubs compared to defining all Hub functionality in a single class.

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

多个集线器没有性能上的差异相比,在一个类中定义的所有集线器功能

回答by Simon_Weaver

SignalR Core - NOT POSSIBLE

SignalR 核心 - 不可能

Unfortunately this is not possible anymore in the new 'Core' version of SignalR

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

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

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

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

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



Notes: Issues with iOS and self signed certificates

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

On iOS there's a limit of FOUR connections per server.

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

Now there isn't this limit for websockets (I think it may be 32 but not sure). HoweverI am using a self signed certificate which has all kinds of issues in Safari - so it actually drops down to long polling (and it's not obvious it's done so).

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

So I ended up with these connections:

所以我最终得到了这些连接:

  • 1 - Angular / Webpack hot reload socket
  • 2 - Web API calls
  • 3 - Hub number one
  • 4 - Hub number two
  • 5 - #&#&#$&#$&
  • 1 - Angular / Webpack 热重载套接字
  • 2 - Web API 调用
  • 3 - 枢纽一号
  • 4 - 第二个集线器
  • 5 - # &#$ &#$&

So if I had ONLY three hubs the whole Safari page would lock up with a blue bar. Even Web API calls got blocked.

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

Note: With HTTP/2 this limit is gonebut you're probably better off limiting yourself to one hubespecially if you're using hot reload. Plus setting up HTTP/2 in development isn't necessarily a trivial task.

注意:使用 HTTP/2 时,此限制已消失,但您最好将自己限制在一个集线器上,尤其是在使用热重载时。另外,在开发中设置 HTTP/2 不一定是一项微不足道的任务。



So how to fix?

那么如何修复呢?

First (temporarily) set your hub to only accept websockets. This will give you an error in Safari (make sure errors are being caught and shown in an alert dialog).

首先(暂时)将您的集线器设置为仅接受 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;
     }
});

Now you'll be able to confirm the fix - run in debug mode, or remove the 'if'.

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

The problem with iOS is even if you accept a self signed certificate for https traffic - and get a nice little 'lock' symbol in the browser - it doesn't apply to the wss: protocol. So connections cannot be upgradedto wss, which is why they block at the max of 4.

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

Solution #1

解决方案#1

If you can get everything down to one hub it's just easier :-)

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

I also realized that multiple hubs complicates reconnect logic if the connection is lost. One hub just makes this easier. If you're not careful you'll end up showing 3 dialog boxes saying 'Connection lost. Retry?' I'm switching to a single hub just because of this.

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

While I hate mixing everything, partial classes help and I personally don't have many SignalR methods anyway.

虽然我讨厌混合所有东西,但部分类有帮助,而且我个人并没有很多 SignalR 方法。

Solution #2

解决方案#2

This is only relevant to debugging, and assumes you're using a https cert which you self-signed.

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

Use instead something like letsencrypt - or Cloudflare's argo tunnel to get a publically trusted cert. This will be fully trusted by Safari, so your connections will get upgraded to real web sockets.

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

Solution #3

解决方案#3

Create a self signed ROOT certificate (CA) and then generate SSL certificates with the domain name from it.

创建一个自签名的 ROOT 证书 (CA),然后使用它的域名生成 SSL 证书。

This was trickier than I imagined. In the end it turned out I was missing Subject Type=CAin my root cert - which iOS requires. Without this 'extension' it will install your root the certificate as a profile, but won't allow you to select it for SSL.

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

Once you have the root cert installed Safari will work with websockets just fine.

一旦你安装了根证书,Safari 就可以很好地与 websockets 一起工作。

Solution #4

解决方案#4

Use http only. This wasn't an option for me because I use certain APIs like Facebook / Google / Payment and they require https.

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

Notes

笔记

  • Important: Now consider production. Realize that websockets may be unavailable for various reasons, so if you have 4 hubs that are connected on iOS this can still cause blocking. You're living dangerously.
  • 重要提示:现在考虑生产。意识到 websockets 可能由于各种原因不可用,所以如果你有 4 个在 iOS 上连接的集线器,这仍然会导致阻塞。你活得很危险。

Better to use one hub in the first place. BUT also best to get your cert installed properly so iOS will work with websockets.

最好一开始就使用一个集线器。但也最好正确安装您的证书,以便 iOS 可以与 websockets 一起使用。

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

如何在没有用户交互的情况下在 Windows 10 中创建和安装 X.509 自签名证书?