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