Exemplo n.º 1
0
Arquivo: MsgKit.cs Projeto: Daoting/dt
        /// <summary>
        /// 若用户在线则推送消息,不在线返回false
        /// </summary>
        /// <param name="p_userID"></param>
        /// <param name="p_msg"></param>
        /// <returns>true 已在线推送,false不在线</returns>
        public static async Task <bool> PushIfOnline(long p_userID, MsgInfo p_msg)
        {
            if (Online.All.TryGetValue(p_userID, out var ls) &&
                ls != null &&
                ls.Count > 0)
            {
                // 本地在线推送
                ls[0].AddMsg(p_msg.GetOnlineMsg());
                return(true);
            }

            // 查询所有其他副本
            int cnt = await Kit.GetSvcReplicaCount();

            if (cnt > 1)
            {
                string key = $"msg:PushIfOnline:{p_userID}:{Guid.NewGuid().ToString().Substring(0, 6)}";
                Kit.RemoteMulticast(new OnlinePushEvent
                {
                    PrefixKey = key,
                    Receivers = new List <long> {
                        p_userID
                    },
                    Msg = p_msg.GetOnlineMsg(),
                    PushFirstSession = true
                });

                // 等待收集
                int total, retry = 0;
                var sc = new StringCache(key);
                do
                {
                    await Task.Delay(_delayMilli);

                    total = await sc.Get <int>("cnt");

                    retry++;
                }while (total < cnt && retry < _maxRetry);

                // 删除统计总数
                await sc.Delete("cnt");

                // 存在键值表示在线
                if (await sc.Delete(null))
                {
                    return(true);
                }
            }
            return(false);
        }
Exemplo n.º 2
0
Arquivo: MsgKit.cs Projeto: Daoting/dt
        /// <summary>
        /// 多副本推送
        /// </summary>
        /// <param name="p_userIDs">用户列表</param>
        /// <param name="p_msg">待推送信息</param>
        /// <param name="p_onlines"></param>
        /// <param name="p_offlines"></param>
        /// <param name="p_cnt"></param>
        static async Task PushMultipleReplicas(List <long> p_userIDs, string p_msg, List <long> p_onlines, List <long> p_offlines, int p_cnt)
        {
            /*
             * Msg服务多副本运行时,有以下两种处理方案:
             * 1. 由当前副本通知所有副本,每个副本都检查会话是否存在,存在时推送并做已推送标志,再由当前副本汇总离线列表
             * 2. 将所有副本的会话信息缓存在redis,当前副本查询缓存获取会话所在的副本,再通过事件总线推送到指定副本
             * 当前采用方案1,因方案2在某个副本非正常退出时,缓存的会话未能与实际同步,造成冗余的推送!
             * 方案1的缺点是所有副本都需要检查会话是否存在
             */

            // 推送结果的前缀键
            string prefixKey = "msg:Push:" + Guid.NewGuid().ToString().Substring(0, 6);

            // 通知所有副本推送
            Kit.RemoteMulticast(new OnlinePushEvent {
                PrefixKey = prefixKey, Receivers = p_userIDs, Msg = p_msg
            });

            // 等待收集
            int total, retry = 0;
            var sc = new StringCache(prefixKey);

            do
            {
                await Task.Delay(_delayMilli);

                total = await sc.Get <int>("cnt");

                retry++;
            }while (total < p_cnt && retry < _maxRetry);

            // 删除统计总数
            await sc.Delete("cnt");

            foreach (long id in p_userIDs)
            {
                // 有记录的表示在线推送成功
                if (await sc.Delete(id))
                {
                    p_onlines.Add(id);
                }
                else
                {
                    p_offlines.Add(id);
                }
            }
        }
Exemplo n.º 3
0
Arquivo: Pusher.cs Projeto: Daoting/dt
        /// <summary>
        /// 注销客户端
        /// 1. 早期版本在客户端关闭时会造成多个无关的ClientInfo收到Abort,只能从服务端Abort,升级到.net 5.0后不再出现该现象!!!
        /// 2. 使用客户端 response.Dispose() 主动关闭时,不同平台现象不同,服务端能同步收到uwp关闭消息,但android ios上不行,
        ///    直到再次推送时才发现客户端已关闭,为了保证客户端在线状态实时更新,客户端只能调用该方法!!!
        /// </summary>
        /// <param name="p_userID"></param>
        /// <param name="p_sessionID">会话标识,区分同一账号多个登录的情况</param>
        /// <returns></returns>
        public async Task <bool> Unregister(long p_userID, string p_sessionID)
        {
            var ci = Online.GetSession(p_userID, p_sessionID);

            if (ci != null)
            {
                await ci.Close();

                return(true);
            }

            // 查询所有其他副本
            int cnt = await Kit.GetSvcReplicaCount();

            if (cnt > 1)
            {
                string key = $"msg:Unregister:{p_userID}:{Guid.NewGuid().ToString().Substring(0, 6)}";
                Kit.RemoteMulticast(new UnregisterEvent {
                    CacheKey = key, UserID = p_userID, SessionID = p_sessionID
                });

                // 等待收集
                int total, retry = 0;
                var sc = new StringCache(key);
                do
                {
                    await Task.Delay(_delayMilli);

                    total = await sc.Get <int>("cnt");

                    retry++;
                }while (total < cnt && retry < _maxRetry);

                // 删除统计总数
                await sc.Delete("cnt");

                // 存在键值表示在线
                if (await sc.Delete(null))
                {
                    return(true);
                }
            }
            return(false);
        }
Exemplo n.º 4
0
Arquivo: Pusher.cs Projeto: Daoting/dt
        /// <summary>
        /// 实时获取所有副本的在线用户总数
        /// </summary>
        /// <returns>Dict结构:key为副本id,value为副本会话总数</returns>
        public async Task <Dict> GetOnlineCount()
        {
            Dict result = null;
            int  cnt    = await Kit.GetSvcReplicaCount();

            if (cnt > 1)
            {
                // 所有副本
                string key = "msg:OnlineCount:" + Guid.NewGuid().ToString().Substring(0, 6);
                Kit.RemoteMulticast(new OnlineCountEvent {
                    CacheKey = key
                });

                // 等待收集
                int total, retry = 0;
                var sc = new StringCache(key);
                do
                {
                    await Task.Delay(_delayMilli);

                    total = await sc.Get <int>("cnt");

                    retry++;
                }while (total < cnt && retry < _maxRetry);

                // 删除统计总数
                await sc.Delete("cnt");

                var hc   = new HashCache(key);
                var hash = await hc.GetAll(null);

                if (hash != null && hash.Length > 0)
                {
                    await hc.Delete(null);

                    result = hash.ToDict();
                }
            }
            else
            {
                // 当前单副本
                result = new Dict {
                    { Kit.SvcID, Online.TotalCount }
                };
            }
            return(result);
        }
Exemplo n.º 5
0
Arquivo: Pusher.cs Projeto: Daoting/dt
        /// <summary>
        /// 查询所有副本,获取某账号的所有会话信息
        /// </summary>
        /// <param name="p_userID"></param>
        /// <returns>会话信息列表</returns>
        public async Task <List <Dict> > GetAllSessions(long p_userID)
        {
            List <Dict> result = new List <Dict>();
            int         cnt    = await Kit.GetSvcReplicaCount();

            if (cnt > 1)
            {
                // 查询所有副本
                string key = $"msg:Sessions:{p_userID}:{Guid.NewGuid().ToString().Substring(0, 6)}";
                Kit.RemoteMulticast(new UserSessionsEvent {
                    CacheKey = key, UserID = p_userID
                });

                // 等待收集
                int total, retry = 0;
                var sc = new StringCache(key);
                do
                {
                    await Task.Delay(_delayMilli);

                    total = await sc.Get <int>("cnt");

                    retry++;
                }while (total < cnt && retry < _maxRetry);

                // 删除统计总数
                await sc.Delete("cnt");

                var hc   = new HashCache(key);
                var hash = await hc.GetAll(null);

                if (hash != null && hash.Length > 0)
                {
                    await hc.Delete(null);

                    var dt = hash.ToDict();
                    foreach (var item in dt)
                    {
                        var ss = Kit.Deserialize <List <Dict> >((string)item.Value);
                        if (ss != null && ss.Count > 0)
                        {
                            result.AddRange(ss);
                        }
                    }
                }
            }
            else
            {
                // 当前单副本
                var ls = Online.GetSessions(p_userID);
                if (ls != null && ls.Count > 0)
                {
                    foreach (var ci in ls)
                    {
                        result.Add(new Dict
                        {
                            { "userid", ci.UserID },
                            { "svcid", Kit.SvcID },
                            { "starttime", ci.StartTime.ToString() },
                            { "platform", ci.Platform },
                            { "version", ci.Version },
                            { "devicename", ci.DeviceName },
                            { "devicemodel", ci.DeviceModel },
                        });
                    }
                }
            }
            return(result);
        }