长轮询是否会在每个请求上创建新的 SignalR Hubs?

Does long polling create new SignalR Hubs on each request?

从 SignalR 的教程中,我了解到集线器 class 的工作方式与 ASP WebForms 页面类似。对于每个请求,都会创建一个新的集线器,处理请求,发送响应,然后销毁。但是,我不太确定我是否理解正确,它如何与各个传输技术一起工作。如果我错了,请纠正我,但我假设如下:

由于 WebSockets 创建了双工通道,因此连接会一直持续到客户端断开连接(或连接因其他原因中断)并且 Hub 的单个实例为发出初始请求的客户端提供服务。

但是,在长轮询中,一旦服务器发送响应,Hub 实例就会被销毁。 SignalR 客户端然后自动创建另一个请求(轮询的性质)。然而,这个请求在服务器上创建了一个全新的 Hub 实例,它与服务于第一个请求的 Hub 对象完全不同。第二个 Hub 实例然后处理请求,发送响应并被销毁。然后客户端发送第三个请求,整个过程再次开始。

我是对还是错?我无法在 Internet 上的任何地方找到答案。

集线器不是按连接创建的,而是按从客户端到服务器的相关请求创建的(我不是在讨论直接在服务器端创建的集线器上下文)。您关于 WebSocket 的陈述 "a single instance of Hub services the client making the initial request" 是错误的。当您在客户端上启动连接并且该过程成功时,将创建一个集线器来触发 OnConnected 事件, 然后它被删除 。当客户端调用服务器端方法时,每次调用都会再次创建一个新的集线器 然后删除 无论您使用何种传输方式,包括 WebSocket,都是如此。集线器 而不是 本身是为了满足物理连接而创建的,因此长时间轮询不是问题,因为它与 WebSocket 没有什么不同。每个 WebSocket 连接或长轮询 HTTP 请求并不意味着创建 persistent hub。集线器是在每个 逻辑 连接 (*) 每个方法调用时创建的临时实例。每次触发连接事件或在集线器上调用方法时,都会有一个新实例响应,无论使用何种传输方式。

This 可能是最值得检查的文档,但是一旦您开始区分逻辑级别(SignalR 事件和方法调用存在于其中)和物理级别(HTTP 请求或 WebSocket,它们不是必然与逻辑层级有关)那就更清楚了

您也可以通过添加如下内容自行验证:

private readonly Guid _id = Guid.NewGuid();

到你的集线器,你会看到任何 OnConnected 事件以及随后的任何方法调用都会有不同的值 无论你选择什么传输方式,因此证明连接和集线器之间不存在一对一的关系(这并不意味着在可能的情况下不会保留底层物理连接,就像使用 WebSocket 一样)。

(*) 这里有些微妙之处使得这个说法并不总是正确的,但它们与传输策略无关,所以我将跳过它们。