【问题标题】:Handling concurrent connections in SiganlR在 SignalR 中处理并发连接
【发布时间】:2016-05-26 08:34:35
【问题描述】:

我正在使用 .Net framework 4.5.2,我将开始制作一个通知系统,该系统将通知从 Web 应用程序发送到从 Windows 窗体桌面应用程序连接的用户。

经过调查,我发现合适的解决方案是使用 signalR,因为它支持在将通知发送到连接的客户端之前过滤通知。

但我担心的是: 当我在 Web 应用程序中创建 HUB 类时,我实现了 OnConnected 方法,该方法将检测连接到服务器以接收通知的任何客户端,我考虑将连接的用户收集到字典中(在内存中)我知道这是一个无法在生产中实现的解决方案,因为在内存变量(字典)中设置连接的用户是不可靠的。在我的情况下,连接用户的数量可能是 20,000 或以上,将来可能会变大。我需要知道跟踪所有连接用户的最佳方式,同时知道处理并发请求的最佳方式,而不会出现任何可伸缩性问题。我是新手,请尽快做出决定。

我还需要知道可以在集线器类中覆盖的 OnReconnect 方法的用途。

如果 iis 出于任何原因重新启动互联网应用程序,我还需要知道如何处理连接以不丢失。

【问题讨论】:

    标签: notifications signalr publish-subscribe signalr-hub signalr-backplane


    【解决方案1】:

    Mapping connections to users 可以通过多种方式完成,具体取决于您想要实现的目标:

    In memory storage
    最好的方法是使用concurrent dictionary。这将允许线程安全操作,但正如您所说,这不是大量连接的最佳解决方案。

    Permanent external storage
    将您的映射保存在数据库中。
    好的部分:映射可跨多个 Web 服务器使用
    坏的部分:数据库压力很大并且需要大量的清理工作

    Single-User Groups
    为每个用户创建一个组。这是最简单实用的解决方案。

    好的部分:
    ~ 真的很容易使用和实现
    ~ SignalR 足够聪明,可以在断开连接时从组中删除连接
    ~ 删除最后一个连接时删除组
    ~ 如果您使用身份,您可以将唯一组名存储为声明 [1] [2] 并通过以下方式将其放入您的集线器:

    public static class IdentityExtensions
    {
        public static string GetSignalRUniqueGroup(this IIdentity identity)
        {
            var claimsIdentity = identity as ClaimsIdentity;
            var claim = claimsIdentity?.FindFirst("uniqueSignalRGroup");
            if (claim == null) return null;
    
            try
            {
                return claim.Value;
            }
            catch
            {
                return null;
            }
        }
    }
    

    (并非如此)不好的部分:您必须小心哪些用户加入了哪些群组。 !不要! 在客户端实现加入组功能。相反,使用 OnConnected 和 OnReconnected 将连接添加到组

    public override Task OnConnected()
    {
        string userGroup = Context.User.Identity.GetSignalRUniqueGroup();
        if(userGroup != null) 
        {
            Groups.Add(Context.ConnectionId, userGroup);
        }
    
        return base.OnConnected();
    }
    
    public override Task OnReconnected()
    {
        string userGroup = Context.User.Identity.GetSignalRUniqueGroup();
        if(userGroup != null) 
        {
            Groups.Add(Context.ConnectionId, userGroup);
        }       
        return base.OnReconnected();
    }
    
    public override Task OnDisconnected(bool stopCalled)
    {
        //You should not manually remove the user from the group when the user disconnects. 
        //This action is automatically performed by the SignalR framework.
        return base.OnDisconnected(stopCalled);
    }
    

    对于其他问题,您可以阅读以下内容: Understanding and Handling Connection Lifetime Events in SignalR

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-20
      • 2017-02-28
      • 2011-08-07
      • 2022-01-06
      • 2011-06-23
      相关资源
      最近更新 更多