使用IoC(Castle Windsor)的SignalR——hub的生命周期应该选择哪种?

5
我刚开始接触SignalR,并创建了一个自定义解析器以便使用Castle Windsor通过hub构造函数注入依赖项。
我原以为只需要注册依赖项,但我发现也需要注册hubs本身才能让我的应用程序正常工作。这是预期的吗?如果是,hubs应该使用什么生命周期?

1
我在这里有一个类似的问题:https://dev59.com/jWEh5IYBdhLWcg3w1mbs - Ian Yates
1个回答

8
默认情况下,SignalR不会将每个Hub注册到依赖项解析器中。相反,它使用一个IAssemblyLocator来查找可能包含SignalR Hubs的可用程序集。然后,IHubDescriptorProvider在所有可用程序集中搜索Hubs并创建HubDescriptors。
最后,IHubActivator接受一个HubDescriptor并返回一个新实例化的SignalR hub(使用Activator.CreateInstance),除非与HubDescriptor关联的Hub类型已在依赖项解析器中注册。在后一种情况下,从IHubActivator返回的Hub将直接从依赖项解析器中获取。
通常,SignalR hubs是短暂的,这意味着它们为每个Hub方法调用创建并销毁。这意味着如果您将您的Hub注册到SignalR的依赖项解析器中,则应确保每次SignalR解析Hub类型时都返回一个新的Hub实例。
我强烈建议不要注册单例Hub,原因有几个:
  1. Hub methods can be called in parallel. When this happens, Hub.Context can be overridden as part of the setup for another method call. This can lead to really subtle bugs. For example, with a singleton Hub, the following code might add a connection other than the caller to a group (which could obviously be a big security issue):

    [Authorize(Roles="Admin")]
    public async Task JoinAdminGroup()
    {
        await Groups.Add(Context.ConnectionId, "admin");
    }
    
  2. Hub.Dispose will be called after each activation. If you keep returning the same Hub, it's Dispose method will be repeatedly called. This probably won't affect you unless you implement Dispose on your Hubs, since the default Dispose implementation currently no-ops.

  3. IIS recycles AppDomains. When this happens, you will be forced to reinstantiate your Hub anyway. Remember, SignalR will automatically reestablish active connections after your app becomes unavailable for a short period of time (as is the case with an AppDomain recycle), so you can very well have a newly instantiated Hub dealing with pre-existing connections even if you register your Hub as a Singleton with the dependency resolver.

https://github.com/SignalR/SignalR/blob/2.0.1/src/Microsoft.AspNet.SignalR.Core/DefaultDependencyResolver.cs#L79


感谢您的有用回答。我猜Transient可能是更好的选择?我想我不应该感到惊讶,因为Web本质上是无状态的,所以每个方法调用都会创建/销毁中心。顺便说一下,我的服务是自托管的,而不是IIS,但我不认为这会有什么区别。 - Andrew Stephens

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接