处理SiganlR中的并发连接

时间:2016-05-26 08:34:35

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

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

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

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

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

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

1 个答案:

答案 0 :(得分:3)

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

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

<强> Permanent external storage
将您的映射保存在数据库中 好的部分:可以跨多个Web服务器使用映射 不好的部分:对数据库施加了很大的压力,需要大量的清理工作

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

好的部分:
〜真的很容易使用和实施
~SignalR足够聪明,可以在断开连接时从组中删除连接 删除最后一个连接时删除〜组 〜如果您使用Identity,则可以将唯一的组名称存储为声明[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