我有以下信号集线器,一个redis背板和一个服务器。像这样在一台服务器上工作很好。现在我需要在多个服务器上运行我的应用程序,但我不知道如何将用户Map到连接,以便在两个服务器上共享signalr connectionid。也许一个解决方案是将connectionmapping存储在redis上,但我不知道怎么做。这就是我现在的解决方案。
我的中心.cs
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)
{
}
}
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);
}
}
}
连接Map.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
}
}
暂无答案!
目前还没有任何答案,快来回答吧!