예제 #1
0
 /// <summary>
 ///    连接容器内部方法,子类可以重写此方法。
 ///    <para>*此方法主要用于确保在使用指定算法获取容器中连接之前,连接容器内部拥有足够多的连接</para>
 ///    <para>*具体策略为优先保证在同步执行代码的情况下,当前连接容器中最少有一个存活的连接,至于剩下的连接需要异步进行创建</para>
 /// </summary>
 protected virtual bool MakeSureConnections()
 {
     if (_connections.Count >= _min || _connections.Count == 1)
     {
         return(true);
     }
     lock (_lockObj)
     {
         try
         {
             IServerConnectionAgent <T> agent = _createFunc(_tuple.Item1, _tuple.Item2, _tuple.Item3);
             //如果当前时间点无法正常创建一个连接代理器,则放弃此次同步机会并改为异步进行
             if (agent == null || !agent.GetChannel().IsConnected)
             {
                 return(false);
             }
             Register(agent);
             return(true);
         }
         catch (System.Exception ex)
         {
             _tracing.Error(ex);
             return(false);
         }
         finally
         {
             if (_connections.Count < _max && Interlocked.CompareExchange(ref _usedBackendThread, 1, 0) == 0)
             {
                 CreateAgentAsync();
             }
         }
     }
 }
예제 #2
0
 /// <summary>
 ///     根据当前负载器规则获取一个通信信道
 /// </summary>
 /// <param name="target">标示网络终点接的协议簇组合</param>
 /// <param name="level">KAE应用等级</param>
 /// <param name="protocolStack">协议栈</param>
 /// <param name="errMsg">错误信息</param>
 /// <param name="selectedRingNode">已选中的一致性HASH圆环节点</param>
 /// <returns>如果指定条件的通信信道不存在,则会创建它并返回</returns>
 /// <exception cref="ArgumentNullException">参数不能为空</exception>
 public IServerConnectionAgent <TMessage> GetChannel(Protocols target, ApplicationLevel level, IProtocolStack protocolStack, out string errMsg, out KAERingNode selectedRingNode)
 {
     lock (_lockObj)
     {
         IDictionary <ApplicationLevel, IDictionary <ProtocolTypes, KetamaRing> > firstLevel;
         if (_addresses.TryGetValue(target, out firstLevel))
         {
             IDictionary <ProtocolTypes, KetamaRing> secondLevel;
             if (firstLevel.TryGetValue(level, out secondLevel))
             {
                 KetamaRing ring;
                 if (secondLevel.TryGetValue(_protocolType, out ring))
                 {
                     if (ring == null)
                     {
                         errMsg           = string.Format("#Sadly, We have no more network information about what you gave of protocol: {0}-{1}-{2}, Maybe it was been removed or there wasn't any available network resources.", target.ProtocolId, target.ServiceId, target.DetailsId);
                         selectedRingNode = null;
                         return(null);
                     }
                     KAERingNode node = ring.GetWorkerNode();
                     IServerConnectionAgent <TMessage> agent = _connectionPool.GetChannel(node.EndPoint, node.RawAddress, protocolStack, _transactionManager);
                     errMsg           = (agent != null ? string.Empty : "#Sadly, We cannot connect to remote endpoint: " + node.RawAddress);
                     selectedRingNode = node;
                     return(agent);
                 }
             }
         }
         errMsg           = string.Format("#Couldn't find any remoting address which it can access it. #Protocol: {0}, #Level: {1}", target, level);
         selectedRingNode = null;
         return(null);
     }
 }
예제 #3
0
        //agent disconnect event handler.
        private void ServerAgentDisconnected(object sender, System.EventArgs e)
        {
            IServerConnectionAgent <T> agent = (IServerConnectionAgent <T>)sender;

            agent.Disconnected -= ServerAgentDisconnected;
            lock (_lockObj) _connections.Remove(agent);
            AgentDisconnectedHandler(new LightSingleArgEventArgs <IServerConnectionAgent <T> >(agent));
        }
예제 #4
0
        void Disconnected(object sender, System.EventArgs e)
        {
            IServerConnectionAgent <BaseMessage> agent = (IServerConnectionAgent <BaseMessage>)sender;

            agent.Disconnected   -= Disconnected;
            agent.NewTransaction -= NewTransaction;
            lock (_lockObj) _agents.Remove(agent);
        }
예제 #5
0
 /// <summary>
 ///     注册一个连接代理器
 /// </summary>
 /// <param name="agent">连接代理器</param>
 /// <exception cref="ArgumentNullException">参数不能为空</exception>
 public void Regist(IServerConnectionAgent <BaseMessage> agent)
 {
     if (agent == null)
     {
         throw new ArgumentNullException(nameof(agent));
     }
     lock (_lockObj) _agents.Add(agent);
     agent.Disconnected   += Disconnected;
     agent.NewTransaction += NewTransaction;
 }
예제 #6
0
        /// <summary>
        ///     创建一个新的事务
        /// </summary>
        /// <param name="role">针对的服务角色</param>
        /// <param name="userId">需要定位的用户编号</param>
        /// <returns>返回新的事务</returns>
        /// <exception cref="ArgumentNullException">参数不能为空</exception>
        public BusinessMessageTransaction CreateTransaction(string role, int userId)
        {
            if (string.IsNullOrEmpty(role))
            {
                throw new ArgumentNullException("role");
            }
            string errMsg;
            IServerConnectionAgent <BaseMessage> agent = _clsuter.GetChannelBySpecificCondition(role, _protocolStacks[role], userId, out errMsg);

            return(agent == null
                       ? new FailMobiSageMessageTransaction(errMsg)
                       : _transactionManager.Create(IdentityHelper.Create((IPEndPoint)agent.GetChannel().LocalEndPoint), agent.GetChannel()));
        }
예제 #7
0
        /// <summary>
        ///     创建一个新的事务
        /// </summary>
        /// <param name="role">针对的服务角色</param>
        /// <returns>返回新的事务</returns>
        /// <exception cref="ArgumentNullException">参数不能为空</exception>
        public MetadataMessageTransaction CreateMetadataTransaction(string role)
        {
            if (string.IsNullOrEmpty(role))
            {
                throw new ArgumentNullException("role");
            }
            string errMsg;
            IServerConnectionAgent <MetadataContainer> agent = _metadataCluster.GetChannel(role, _metadataProtocolStack, out errMsg);

            return(agent == null
                       ? new FailMobiSageMetadataTransaction(errMsg)
                       : _metadataTransactionManager.Create(IdentityHelper.Create((IPEndPoint)agent.GetChannel().LocalEndPoint), agent.GetChannel()));
        }
예제 #8
0
 /// <summary>
 ///    向当前的连接容器中注册一个存活的连接
 /// </summary>
 /// <param name="agent"></param>
 public virtual void Register(IServerConnectionAgent <T> agent)
 {
     if (agent == null)
     {
         return;
     }
     if (!agent.GetChannel().IsConnected)
     {
         AgentDisconnectedHandler(new LightSingleArgEventArgs <IServerConnectionAgent <T> >(agent));
         return;
     }
     agent.Disconnected += ServerAgentDisconnected;
     lock (_lockObj) _connections.Add(agent);
 }
예제 #9
0
        /// <summary>
        ///     创建一个新的单向通信事务
        ///     <para>* 使用此函数创建的事务是单向通信的,也就意味着新的事务不会触发RecvRsp事件</para>
        /// </summary>
        /// <param name="role">针对的服务角色</param>
        /// <returns>返回新的事务</returns>
        /// <exception cref="ArgumentNullException">参数不能为空</exception>
        public BusinessMessageTransaction CreateOnewayTransaction(string role)
        {
            if (string.IsNullOrEmpty(role))
            {
                throw new ArgumentNullException("role");
            }
            string errMsg;
            IServerConnectionAgent <BaseMessage> agent = _clsuter.GetChannel(role, _protocolStacks[role], out errMsg);

            return(agent == null
                       ? new FailMobiSageMessageTransaction(errMsg)
                       : new BusinessMessageTransaction(new Lease(DateTime.MaxValue), agent.GetChannel())
            {
                Identity = IdentityHelper.CreateOneway((IPEndPoint)agent.GetChannel().LocalEndPoint)
            });
        }
예제 #10
0
        /// <summary>
        ///     创建一个新的事务
        ///     <para>* 按照固定手机号的负载策略</para>
        /// </summary>
        /// <param name="targetRole">针对的服务角色</param>
        /// <param name="protocolSelf">使用的协议栈</param>
        /// <param name="mobileNo">手机号</param>
        /// <returns>返回新的事务</returns>
        /// <exception cref="ArgumentNullException">参数不能为空</exception>
        public BusinessMessageTransaction CreateTransaction(string targetRole, string protocolSelf, long mobileNo)
        {
            if (string.IsNullOrEmpty(targetRole))
            {
                throw new ArgumentNullException("targetRole");
            }
            if (string.IsNullOrEmpty(protocolSelf))
            {
                throw new ArgumentNullException("protocolSelf");
            }
            string errMsg;
            IServerConnectionAgent <BaseMessage> agent = _clsuter.GetChannelBySpecificCondition(targetRole, _protocolStacks[protocolSelf], mobileNo, out errMsg);

            return(agent == null
                       ? new FailMobiSageMessageTransaction(errMsg)
                       : _transactionManager.Create(IdentityHelper.Create((IPEndPoint)agent.GetChannel().LocalEndPoint), agent.GetChannel()));
        }
예제 #11
0
        /// <summary>
        ///     创建一个新的单向通信事务
        ///     <para>* 使用此函数创建的事务是单向通信的,也就意味着新的事务不会触发RecvRsp事件</para>
        /// </summary>
        /// <param name="targetRole">针对的服务角色</param>
        /// <param name="protocolSelf">使用的协议栈</param>
        /// <param name="userId">需要定位的用户编号</param>
        /// <returns>返回新的事务</returns>
        /// <exception cref="ArgumentNullException">参数不能为空</exception>
        public BusinessMessageTransaction CreateOnewayTransaction(string targetRole, string protocolSelf, int userId)
        {
            if (string.IsNullOrEmpty(targetRole))
            {
                throw new ArgumentNullException("targetRole");
            }
            if (string.IsNullOrEmpty(protocolSelf))
            {
                throw new ArgumentNullException("protocolSelf");
            }
            string errMsg;
            IServerConnectionAgent <BaseMessage> agent = _clsuter.GetChannelBySpecificCondition(protocolSelf, _protocolStacks[protocolSelf], userId, out errMsg);

            return(agent == null
                       ? new FailMobiSageMessageTransaction(errMsg)
                       : new BusinessMessageTransaction(new Lease(DateTime.MaxValue), agent.GetChannel())
            {
                Identity = IdentityHelper.CreateOneway((IPEndPoint)agent.GetChannel().LocalEndPoint)
            });
        }
예제 #12
0
 /// <summary>
 ///    使用后台线程的方式异步地创建连接代理器
 /// </summary>
 private void CreateAgentAsync()
 {
     if (_backendThread != null)
     {
         return;
     }
     _backendThread = new Thread(delegate()
     {
         int retryCount = 0;
         while (_connections.Count < _max)
         {
             try
             {
                 IServerConnectionAgent <T> agent = _createFunc(_tuple.Item1, _tuple.Item2, _tuple.Item3);
                 //如果当前时间点无法正常创建一个连接代理器,则默认行为是重试3次
                 if (agent == null || !agent.GetChannel().IsConnected)
                 {
                     if (retryCount < 3)
                     {
                         retryCount++;
                         continue;
                     }
                     Interlocked.Exchange(ref _usedBackendThread, 0);
                     _backendThread = null;
                     break;
                 }
                 //reset retry counter.
                 retryCount = 0;
                 Register(agent);
             }
             catch (System.Exception ex) { _tracing.Error(ex); }
         }
         Interlocked.Exchange(ref _usedBackendThread, 0);
         _backendThread = null;
     })
     {
         IsBackground = true, Name = "ConnectionSet-Backend-Thread"
     };
     _backendThread.Start();
 }
        /// <summary>
        ///     创建一个新的网络事务
        /// </summary>
        /// <param name="appName">目标APP的名称</param>
        /// <param name="target">标示网络终点接的协议簇组合</param>
        /// <param name="maximumRspTime">等待当前网络事务RSP消息的最大时间</param>
        /// <param name="resourceUri">KAE资源URI</param>
        /// <param name="balanceFlag">负载标识</param>
        /// <param name="communicationType">通信方式</param>
        /// <param name="version">
        ///     目标APP的版本
        ///     <para>* 默认为: latest</para>
        /// </param>
        /// <param name="protocolSelf">
        ///     使用的协议栈的角色
        ///     <para>* 如果当前事务代理器所承载的消息协议为MetadataContainer时请忽略此参数</para>
        /// </param>
        /// <returns>返回新的事务</returns>
        public IMessageTransaction <TMessage> CreateTransaction(string appName, Protocols target, TimeSpan maximumRspTime, long balanceFlag, string version = "latest", KAEResourceUri resourceUri = null, NetworkCommunicationTypes communicationType = NetworkCommunicationTypes.Dulplex, string protocolSelf = null)
        {
            if (string.IsNullOrEmpty(appName))
            {
                throw new ArgumentNullException("appName");
            }
            string           errMsg;
            ApplicationLevel level = (resourceUri == null ? ApplicationLevel.Stable : _callback(resourceUri));
            KAERingNode      ringNode;
            IServerConnectionAgent <TMessage> agent = _cluster.GetChannel(target, level, _container.GetDefaultProtocolStack(_cluster.ProtocolType), balanceFlag, out errMsg, out ringNode);

            if (agent == null)
            {
                lock (_lockObj)
                {
                    //try to obtains agent object again for ensuring that the newest remoting addresses can be appliy in the multiple threading env.
                    agent = _cluster.GetChannel(target, level, _container.GetDefaultProtocolStack(_cluster.ProtocolType), balanceFlag, out errMsg, out ringNode);
                    if (agent == null && !GetMissedRemoteAddresses(appName, version, target, level))
                    {
                        return(new FailMessageTransaction <TMessage>(errMsg));
                    }
                    agent = _cluster.GetChannel(target, level, _container.GetDefaultProtocolStack(_cluster.ProtocolType), balanceFlag, out errMsg, out ringNode);
                    //check returned value again for avoiding couldnt connect to the remote address now.
                    if (agent == null)
                    {
                        return(new FailMessageTransaction <TMessage>(errMsg));
                    }
                }
            }
            MessageTransaction <TMessage> transaction = NewTransaction(new Lease(DateTime.Now.Add(maximumRspTime)), agent.GetChannel());

            transaction.SetMessageIdentity(new MessageIdentity {
                ProtocolId = (byte)target.ProtocolId, ServiceId = (byte)target.ServiceId, DetailsId = (byte)target.DetailsId
            });
            transaction.TransactionManager = _transactionManager;
            transaction.Identity           = (communicationType == NetworkCommunicationTypes.Dulplex ? IdentityHelper.Create(agent.GetChannel().LocalEndPoint, TransportChannelTypes.TCP) : IdentityHelper.CreateOneway(agent.GetChannel().LocalEndPoint, TransportChannelTypes.TCP));
            transaction.KPPUniqueId        = ringNode.KPPUniqueId;
            return(_transactionManager.Add(transaction.Identity, transaction) ? transaction : null);
        }