长轮询是否会在每个请求上创建新的 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 一样)。
(*) 这里有些微妙之处使得这个说法并不总是正确的,但它们与传输策略无关,所以我将跳过它们。
从 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 一样)。
(*) 这里有些微妙之处使得这个说法并不总是正确的,但它们与传输策略无关,所以我将跳过它们。