到多个服务器上Map的用户的信号器连接

f5emj3cl  于 2021-06-08  发布在  Redis
关注(0)|答案(0)|浏览(189)

我有以下信号集线器,一个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
    }
}

暂无答案!

目前还没有任何答案,快来回答吧!

相关问题