C# 到多台服务器上映射的用户的信令连接
我有以下信号集线器、一个Redis背板和一台服务器。 在一台服务器上这样工作非常好。 现在,我需要在多台服务器上运行我的应用程序,但我不知道如何映射 将用户连接到连接,以便在两台服务器上共享signalR ConnectionId。 也许一个解决方案是将ConnectionMapping存储在Redis上,但我不知道如何实现。 这就是我的解决方案目前的工作方式 MyHub.csC# 到多台服务器上映射的用户的信令连接,c#,asp.net-mvc-4,redis,signalr,C#,Asp.net Mvc 4,Redis,Signalr,我有以下信号集线器、一个Redis背板和一台服务器。 在一台服务器上这样工作非常好。 现在,我需要在多台服务器上运行我的应用程序,但我不知道如何映射 将用户连接到连接,以便在两台服务器上共享signalR ConnectionId。 也许一个解决方案是将ConnectionMapping存储在Redis上,但我不知道如何实现。 这就是我的解决方案目前的工作方式 MyHub.cs public class MyHub : Hub { #region Init
public class MyHub : Hub
{
#region Init
private static IHubContext GetHubContext => GlobalHost.ConnectionManager.GetHubContext<MyHub>();
public MyHub()
{
}
#endregion Init
#region Connection Management events
public Task JoinGroup(string groupName)
{
return Groups.Add(Context.ConnectionId, groupName);
}
public Task LeaveGroup(string groupName)
{
return Groups.Remove(Context.ConnectionId, groupName);
}
[Authorize]
public override Task OnConnected()
{
if (Context.User != null)
{
if (Context.User.Identity.IsAuthenticated)
{
var userId = Context.User.Identity.GetUserId<int>();
if (userId == 0)
{
var userManager = HttpContext.Current.GetOwinContext().GetUserManager<MyUserManager>();
var user = userManager.FindByName(Context.User.Identity.Name);
if (user != null)
userId = user.Id;
}
var userRoles = UserRoles.GetAll().Where(x => Context.User.IsInRole(x)).ToArray();
ConnectionMappingsService.AddConnectionAsync(Context.ConnectionId, userId, userRoles);
if (Context.User.IsInRole(UserRoles.Admin))
UserStatusChanged(userId, true);
}
}
return base.OnConnected();
}
[Authorize]
public override Task OnDisconnected(bool stopCalled)
{
UserDisconnectedAsync(Context.ConnectionId);
return base.OnDisconnected(stopCalled);
}
public static async Task MessageCreatedMobile(int userId)
{
var SignalRMessage = new
{
ClientEvent = "Message",
Flag = "Update",
Target “Test”
};
var recipientConnectionIds = await ConnectionMappingsService.GetUserConnectionsAsync(userId);
var hubContext = GlobalHost.ConnectionManager.GetHubContext<MyHub>();// GetHubContext;
try
{
foreach (var connection in recipientConnectionIds)
{
hubContext.Clients.Client(connection).send(SignalRMessage);
}
}
catch (Exception ex)
{
}
}
公共类MyHub:Hub
{
#区域初始化
私有静态IHubContext GetHubContext=>GlobalHost.ConnectionManager.GetHubContext();
公共MyHub()
{
}
#端域初始化
#区域连接管理事件
公共任务组(字符串组名)
{
返回Groups.Add(Context.ConnectionId,groupName);
}
公共任务组(字符串组名)
{
返回Groups.Remove(Context.ConnectionId,groupName);
}
[授权]
已连接的公用覆盖任务()
{
if(Context.User!=null)
{
if(Context.User.Identity.IsAuthenticated)
{
var userId=Context.User.Identity.GetUserId();
if(userId==0)
{
var userManager=HttpContext.Current.GetOwinContext().GetUserManager();
var user=userManager.FindByName(Context.user.Identity.Name);
如果(用户!=null)
userId=user.Id;
}
var userRoles=userRoles.GetAll().Where(x=>Context.User.IsInRole(x)).ToArray();
ConnectionMappingService.AddConnectionAsync(Context.ConnectionId、userId、userRoles);
if(Context.User.IsInRole(UserRoles.Admin))
UserStatusChanged(userId,true);
}
}
返回base.OnConnected();
}
[授权]
公共覆盖任务OnDisconnected(bool stopCalled)
{
UserDisconnectedAsync(Context.ConnectionId);
返回基.OnDisconnected(stopCalled);
}
公共静态异步任务MessageCreatedMobile(int userId)
{
var信号消息=新建
{
ClientEvent=“Message”,
Flag=“更新”,
目标“测试”
};
var RecipientConnectionId=await ConnectionMappingService.GetUserConnectionAsync(用户ID);
var hubContext=GlobalHost.ConnectionManager.GetHubContext();//GetHubContext;
尝试
{
foreach(RecipientConnectionId中的var连接)
{
hubContext.Clients.Client(connection).send(SignalRMessage);
}
}
捕获(例外情况除外)
{
}
}
ConnectionMappingService.cs
public static class ConnectionMappingsService
{
private static readonly ConnectionMapping<int> UsersConnections = new ConnectionMapping<int>();
private static readonly ConnectionMapping<string> RoleConnections = new ConnectionMapping<string>();
public static async Task AddConnectionAsync(string connectionId, int userId, string[] roles)
{
var userConnectionTask = UsersConnections.AddAsync(new int[] { userId }, connectionId);
var roleConnectionTask = RoleConnections.AddAsync(roles, connectionId);
await Task.WhenAll(userConnectionTask, roleConnectionTask);
}
public static async Task AddConnectionIfAbsentAsync(string connectionId, int userId, string[] roles)
{
var userConnectionTask = UsersConnections.AddIfAbsentAsync(new int[] { userId }, connectionId);
var roleConnectionTask= RoleConnections.AddIfAbsentAsync(roles, connectionId);
await Task.WhenAll(userConnectionTask, roleConnectionTask);
}
public static async Task<ConnectionDataDto> RemoveConnectionAsync(string connectionId)
{
var result = new ConnectionDataDto();
result.UserIds = await UsersConnections.RemoveAsync(connectionId);
result.Roles = await RoleConnections.RemoveAsync(connectionId);
return result;
}
public static async Task<IEnumerable<string>> GetUserConnectionsAsync(int userId)
{
return await UsersConnections.GetConnectionsAsync(new int[] { userId });
}
public static async Task<IEnumerable<string>> GetUserConnectionsAsync(int[] userIds)
{
return await UsersConnections.GetConnectionsAsync(userIds);
}
public static async Task<IEnumerable<string>> GetRoleConnectionsAsync(string[] roles)
{
return await RoleConnections.GetConnectionsAsync(roles);
}
public static async Task<bool> UserHasConnectionsAsync(int userId)
{
return await UsersConnections.AnyConnectionsAsync(userId);
}
}
}
公共静态类ConnectionMappingService
{
私有静态只读ConnectionMapping UsersConnections=new ConnectionMapping();
私有静态只读ConnectionMapping RoleConnections=新ConnectionMapping();
公共静态异步任务AddConnectionAsync(字符串connectionId、int userId、字符串[]角色)
{
var userConnectionTask=UsersConnections.AddAsync(新的int[]{userId},connectionId);
var roleConnectionTask=RoleConnections.AddAsync(角色,连接ID);
wait Task.WhenAll(userConnectionTask、roleConnectionTask);
}
公共静态异步任务addConnectionFabSentAsync(字符串connectionId,int userId,字符串[]角色)
{
var userConnectionTask=UsersConnections.AddIfAbsentAsync(新的int[]{userId},connectionId);
var roleConnectionTask=RoleConnections.AddIfAbsentAsync(角色,连接ID);
wait Task.WhenAll(userConnectionTask、roleConnectionTask);
}
公共静态异步任务RemoveConnectionAsync(字符串connectionId)
{
var result=new connectiondatato();
result.UserIds=await UsersConnections.RemoveAsync(connectionId);
result.Roles=wait RoleConnections.RemoveAsync(connectionId);
返回结果;
}
公共静态异步任务GetUserConnectionAsync(int userId)
{
返回wait UsersConnections.getConnectionAsync(新的int[]{userId});
}
公共静态异步任务GetUserConnectionAsync(int[]userIds)
{
返回wait UsersConnections.getConnectionAsync(userid);
}
公共静态异步任务GetRoleConnectionsAsync(字符串[]角色)
{
返回wait-RoleConnections.getConnectionAsync(角色);
}
公共静态异步任务UserHasConnectionAsync(int userId)
{
返回wait UsersConnections.anyconnectionasync(userId);
}
}
}
ConnectionMapping.cs
public class ConnectionMapping<T>
{
private readonly Dictionary<T, HashSet<string>> _connections = new Dictionary<T, HashSet<string>>();
public async Task<int> CountAsync()
{
return await Task.Run(()=> Count());
}
public async Task AddAsync(T[] keys, string connectionId)
{
await Task.Run(() => Add(keys, connectionId));
}
public async Task AddIfAbsentAsync(T[] keys, string connectionId)
{
await Task.Run(() => AddIfAbsent(keys,connectionId));
}
public async Task<IEnumerable<string>> GetConnectionsAsync(T[] keys)
{
return await Task.Run(() => GetConnections(keys));
}
public async Task<T[]> RemoveAsync(string connectionId)
{
return await Task.Run(()=>Remove(connectionId) ) ;
}
public async Task<T[]> GetConnectionKeysAsync(string connectionId)
{
return await Task.Run(() => GetConnectionKeys(connectionId));
}
public async Task<bool> AnyConnectionsAsync(T key)
{
return await Task.Run(() => AnyConnections(key));
}
#region NonAsync
public int Count()
{
lock (_connections)
{
return _connections.Count;
}
}
public void Add(T[] keys, string connectionId)
{
if (keys == null || !keys.Any())
return;
lock (_connections)
{
foreach (T key in keys)
{
HashSet<string> connections;
if (!_connections.TryGetValue(key, out connections))
{
connections = new HashSet<string>();
_connections.Add(key, connections);
}
lock (connections)
{
connections.Add(connectionId);
}
}
}
}
public void AddIfAbsent(T[] keys, string connectionId)
{
if (keys == null || !keys.Any())
return;
lock (_connections)
{
foreach (T key in keys)
{
HashSet<string> connections;
if (!_connections.TryGetValue(key, out connections))
{
connections = new HashSet<string>();
_connections.Add(key, connections);
}
lock (connections)
{
if (!connections.Contains(connectionId))
connections.Add(connectionId);
}
}
}
}
public IEnumerable<string> GetConnections(T[] keys)
{
var result = new HashSet<string>();
lock (_connections)
{
foreach (var key in keys)
{
HashSet<string> connections;
if (_connections.TryGetValue(key, out connections))
{
result.UnionWith(connections);
}
}
}
return result as IEnumerable<string>;
}
public T[] Remove(string connectionId)
{
T[] keys;
lock (_connections)
{
keys = _connections.Where(x => x.Value.Contains(connectionId)).Select(x => x.Key).ToArray();
foreach (var key in keys)
{
HashSet<string> connections;
if (!_connections.TryGetValue(key, out connections))
{
continue;
}
lock (connections)
{
connections.Remove(connectionId);
if (connections.Count == 0)
{
_connections.Remove(key);
}
}
}
}
return keys;
}
public T[] GetConnectionKeys(string connectionId)
{
lock (_connections)
{
var keys = _connections.Where(x => x.Value.Contains(connectionId)).Select(x => x.Key).ToArray();
return keys;
}
}
public bool AnyConnections(T key)
{
lock (_connections)
{
HashSet<string> connections;
if (!_connections.TryGetValue(key, out connections))
{
return false;
}
else
{
return connections.Any();
}
}
}
#endregion NonAsync
}
}
公共类连接映射
{
专用只读词典_connections=new Dictionary();
公共异步任务CountAsync()
{
返回等待任务。运行(()=>Count());
}
公共异步任务AddAsync(T[]键,字符串连接ID)
{
等待任务。运行(()=>Add(key,connectionId));
}
公共异步任务AddIfAbsentAsync(T[]键,字符串连接ID)
{
等待任务。运行(()=>AddFabSent(键,连接ID));
}
公共异步任务GetConnectionAsync(T[]键)
{
返回等待任务。运行(()=>GetConnections(键));
}
公共异步任务RemoveAsync(字符串连接ID)
{
返回等待任务。运行(()=>Remove(connectionId));
}
公共异步任务GetConnectionKeysA