【问题标题】:Does long polling create new SignalR Hubs on each request?长轮询是否会在每个请求上创建新的 SignalR 集线器?
【发布时间】:2015-04-04 00:09:00
【问题描述】:

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

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

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

我是对还是错?我在互联网上的任何地方都找不到答案。

【问题讨论】:

    标签: c# asp.net signalr


    【解决方案1】:

    集线器不是根据连接创建的,而是根据从客户端到服务器的相关请求创建的(我不是在讨论直接在服务器端创建的集线器上下文)。您关于 WebSocket 的声明“一个 Hub 服务客户端发出初始请求” 是错误的。当您在客户端上启动连接并且该过程成功时,将创建一个集线器以触发OnConnected 事件,然后将其删除。当客户端调用服务器端方法时,再次为每个调用创建一个新的集线器然后删除无论您使用什么传输方式,包括 WebSocket,这都是正确的。集线器不是为了满足物理连接本身而创建的,因此长时间轮询它不是问题,因为它与 WebSocket 没有什么不同。每个 WebSocket 连接或长轮询 HTTP 请求并不意味着创建 持久 集线器。集线器是在每个 逻辑 连接 (*) 每个方法调用时创建的瞬态实例。每次在集线器上触发连接事件或调用方法时,都会有一个新实例响应,无论使用何种传输。

    This 可能是最好的检查文档,但是一旦您开始区分逻辑级别(SignalR 事件和方法调用现场)与物理级别(HTTP 请求或 WebSocket,它们不一定与逻辑层面)那么它应该更清晰。

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

    private readonly Guid _id = Guid.NewGuid();
    

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

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

    【讨论】:

    • 感谢您解决这个问题。没有意识到为每次调用都创建了集线器。你提到有例外 - 你能详细说明吗?有没有办法让集线器不是瞬态的?谢谢!
    • @CoderBang 自从那个回复以来已经有一段时间了,所以我不确定我在想什么 :) 可能是因为,如果你愿意,你可以使用 SignalR 的内部结构并更改集线器创建策略,因此可能会引入缓存实例的方法,但我认为除非您真的不去那里并破解开箱即用的工作方式,否则流行的行为就是所描述的行为。如果我的意思是别的,我已经记不起来了。
    • 请求管道在 websocket 的生命周期内只创建一次,但对于每个长轮询请求都会一遍又一遍地创建。请记住,这与 Hub 本身是分开的,并且只有在您执行自定义中间件身份验证模块之类的操作时才会影响您。或者,如果您使用 context.environment,它会为网络请求保留,但会在每次长轮询时被覆盖。
    猜你喜欢
    • 2017-07-05
    • 1970-01-01
    • 2014-02-03
    • 2021-05-24
    • 2020-07-13
    • 2017-01-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多