예제 #1
0
 /// <summary>
 /// 归还一个连接至连接池
 /// </summary>
 /// <param name="client">连接</param>
 public virtual void ReturnClient(ISerClient client)
 {
     lock (locker)
     {
         //空闲连接数达到上限或者连接版本过期,不再返回线程池,直接销毁
         if (idleCount >= MaxIdle ||
             this.Version != client.Version)
         {
             DestoryClient(client);
         }
         else
         {
             //if (ValidateClient(client))
             //{
             //    //有效连接回归连接池
             //    client.Reset();
             //    EnqueueClient(client);
             //}
             //else
             //{
             //    //无效连接回收
             //    DestoryClient(client);
             //}
             //连接回归连接池
             EnqueueClient(client);
             //发通知信号,连接池有连接变动
             resetEvent.Set();
         }
     }
 }
예제 #2
0
 /// <summary>
 /// 销毁连接
 /// </summary>
 /// <param name="client">连接</param>
 protected void DestoryClient(ISerClient client)
 {
     if (client != null)
     {
         client.Close();
     }
     activeCount--;
 }
예제 #3
0
        /// <summary>
        /// 校验连接,确保连接开启
        /// </summary>
        /// <param name="client">连接</param>

        protected bool ValidateClient(ISerClient client)
        {
            try
            {
                client.Open();
                return(true);
            }
            catch
            {
                return(false);
            }
        }
예제 #4
0
        /// <summary>
        /// 校验连接,确保连接开启
        /// </summary>
        /// <param name="client">连接</param>

        protected bool ValidateClient(ISerClient client, out Exception err)
        {
            try
            {
                client.Open();
                err = null;
                return(true);
            }
            catch (Exception e)
            {
                err = e;
                return(false);
            }
        }
예제 #5
0
        /// <summary>
        /// 从连接池取出一个连接
        /// </summary>
        /// <returns>连接</returns>
        public virtual ISerClient BorrowClient()
        {
            lock (locker)
            {
                ISerClient client = null;
                //连接池无空闲连接

                if (idleCount == 0)
                {
                    //连接池已已创建连接数达上限
                    if (activeCount >= MaxActive)
                    {
                        if (!resetEvent.WaitOne(ClientTimeout))
                        {
                            throw new TimeoutException("连接池繁忙,暂无可用连接。");
                        }
                    }
                    else
                    {
                        var candiate = InitializeClient();
                        if (candiate != null)
                        {
                            EnqueueClient(candiate);
                        }
                        else
                        {
                            throw new InvalidOperationException("连接获取失败,请确认调用服务状态。");
                        }
                    }
                }
                client = DequeueClient();

                //空闲连接数小于最小空闲数,添加一个连接到连接池(已创建数不能超标)
                if (idleCount < MinIdle && activeCount < MaxActive)
                {
                    var candiate = InitializeClient();
                    if (candiate != null)
                    {
                        EnqueueClient(candiate);
                    }
                }

                return(client);
            }
        }
예제 #6
0
 /// <summary>
 /// 初始化连接,隐藏创建细节
 /// </summary>
 /// <returns>连接</returns>
 protected ISerClient InitializeClient()
 {
     for (var i = 0; i < Hosts.Length; i++)
     {
         try
         {
             var        threadId  = Thread.CurrentThread.ManagedThreadId;
             var        hostIndex = (threadId + i) % Hosts.Length;
             ISerClient client    = CreateClient(Hosts[hostIndex]);
             if (ValidateClient(client))
             {
                 activeCount++;
                 client.Reset();
                 return(client);
             }
         }
         catch
         {
             continue;
         }
     }
     return(null);
 }
예제 #7
0
        /// <summary>
        /// 初始化连接,隐藏创建细节
        /// </summary>
        /// <returns>连接</returns>
        protected ISerClient InitializeClient(out Exception err)
        {
            err = null;
            if (Hosts.Length == 0)
            {
                err = new NullReferenceException("没有可用服务节点");
                return(null);
            }
            var hostIndexs = new int[Hosts.Length];
            int j          = 0;

            for (var i = 0; i < Hosts.Length; i++)
            {
                hostIndexs[i] = i;
            }
            for (var i = 0; i < Hosts.Length; i++)
            {
                try
                {
                    j = rand.Next(Hosts.Length);
                    ISerClient client = CreateClient(Hosts[hostIndexs[j]]);
                    if (ValidateClient(client, out err))
                    {
                        activeCount++;
                        client.Reset();
                        return(client);
                    }
                }
                catch (Exception e)
                {
                    hostIndexs[j] = hostIndexs[(j + 1) % Hosts.Length];
                    err           = e;
                    continue;
                }
            }
            return(null);
        }
예제 #8
0
        /// <summary>
        /// 获取服务连接
        /// </summary>
        /// <param name="serviceName">服务名</param>
        /// <param name="protocolTags">协议标签,决定连接池类型,默认使用配置内指定标签</param>
        /// <returns>服务连接</returns>
        public ISerClient GetServiceClient(string serviceName, string protocolTags = null)
        {
            //参数检查
            ISerClient client = null;

            protocolTags = protocolTags ?? ConsulCache.Instance.GetServiceTags(serviceName);
            if (string.IsNullOrEmpty(serviceName) ||
                string.IsNullOrEmpty(protocolTags))
            {
                return(client);
            }

            //筛选有效协议标签
            string protocolTag = null;

            foreach (var tag in protocolTags.Split(','))
            {
                switch (tag)
                {
                case "http":
                case "thrift":
                case "wcf":
                case "grpc":
                    protocolTag = tag;
                    break;

                default:
                    continue;
                }
            }
            if (protocolTag == null)
            {
                return(client);
            }

            //获取或创建连接池
            var     poolKey = string.Join(":", serviceName, protocolTag);
            SerPool pool    = null;

            if (serverPools.ContainsKey(poolKey))
            {
                pool = serverPools[poolKey];
            }
            else
            {
                lock (serviceLock)
                {
                    if (serverPools.ContainsKey(poolKey))
                    {
                        pool = serverPools[poolKey];
                    }
                    else
                    {
                        //读取连接池配置值
                        var config = new SerConfig();
                        foreach (var key in ConsulCache.Instance.GetKeys())
                        {
                            if (key.Contains(poolKey))
                            {
                                var configKey = key.Split(':').Last();
                                config.Add(configKey, GetKeyValue(key));

                                //设置键值回调
                                AddKvHook(key, (k, v) =>
                                {
                                    config[k.Split(':').Last()] = v;
                                });
                            }
                        }
                        //配置加入服务名
                        config.Add("ServiceName", serviceName);

                        //创建连接池
                        switch (protocolTag)
                        {
                        case "http":
                            pool = new HttpPool(GetServiceHosts(serviceName, protocolTags),
                                                config);
                            break;

                        case "thrift":
                            pool = new ThriftPool(GetServiceHosts(serviceName, protocolTags),
                                                  config);
                            break;

                        case "wcf":
                            pool = new WcfPool(GetServiceHosts(serviceName, protocolTags),
                                               config);
                            break;

                        case "grpc":
                            pool = new GrpcPool(GetServiceHosts(serviceName, protocolTags),
                                                config);
                            break;

                        default:
                            return(client);
                        }

                        //设置连接池重置回调,负载信息变更
                        AddServiceHook(serviceName, (s) =>
                        {
                            pool.ResetPool(GetServiceHosts(s, ConsulCache.Instance.GetServiceTags(s)));
                        });

                        //添加连接池
                        serverPools.Add(poolKey, pool);
                    }
                }
            }

            //返回连接
            return(pool.BorrowClient());
        }
예제 #9
0
 /// <summary>
 /// 连接进入连接池
 /// </summary>
 /// <param name="client">连接</param>
 protected void EnqueueClient(ISerClient client)
 {
     clientsPool.Enqueue(client);
     idleCount++;
 }
예제 #10
0
        /// <summary>
        /// 从连接池取出一个连接
        /// </summary>
        /// <returns>连接</returns>
        public virtual ISerClient BorrowClient()
        {
            if (Monitor.TryEnter(locker, TimeSpan.FromMilliseconds(ClientTimeout)))
            {
                try
                {
                    ISerClient client      = null;
                    Exception  innerErr    = null;
                    var        validClient = false;
                    //连接池无空闲连接

                    if (idleCount > 0 && !validClient)
                    {
                        client      = DequeueClient();
                        validClient = ValidateClient(client, out innerErr);
                        if (!validClient)
                        {
                            DestoryClient(client);
                        }
                    }

                    //连接池无空闲连接
                    if (!validClient)
                    {
                        //连接池已已创建连接数达上限
                        if (activeCount > MaxActive)
                        {
                            if (!resetEvent.WaitOne(ClientTimeout))
                            {
                                throw new TimeoutException("连接池繁忙,暂无可用连接。");
                            }
                        }
                        else
                        {
                            client = InitializeClient(out innerErr);
                            if (client == null)
                            {
                                throw new InvalidOperationException("连接获取失败,请确认调用服务状态。", innerErr);
                            }
                        }
                    }

                    //空闲连接数小于最小空闲数,添加一个连接到连接池(已创建数不能超标)
                    if (idleCount < MinIdle && activeCount < MaxActive)
                    {
                        var candiate = InitializeClient(out innerErr);
                        if (candiate != null)
                        {
                            EnqueueClient(candiate);
                        }
                    }

                    return(client);
                }
                finally
                {
                    Monitor.Exit(locker);
                }
            }
            else
            {
                throw new TimeoutException("获取连接等待超过" + ClientTimeout + "毫秒。");
            }
        }
예제 #11
0
 /// <summary>
 /// 初始化
 /// </summary>
 /// <param name="client">初始化</param>
 public CommonStub(ISerClient client)
 {
     this.client = client;
     chanelType  = Type.GetType(client.Owner.Config["ChanelType"]);
     realStub    = client.GetStub(chanelType);
 }