/// <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(); } } }
/// <summary> /// 销毁连接 /// </summary> /// <param name="client">连接</param> protected void DestoryClient(ISerClient client) { if (client != null) { client.Close(); } activeCount--; }
/// <summary> /// 校验连接,确保连接开启 /// </summary> /// <param name="client">连接</param> protected bool ValidateClient(ISerClient client) { try { client.Open(); return(true); } catch { return(false); } }
/// <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); } }
/// <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); } }
/// <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); }
/// <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); }
/// <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()); }
/// <summary> /// 连接进入连接池 /// </summary> /// <param name="client">连接</param> protected void EnqueueClient(ISerClient client) { clientsPool.Enqueue(client); idleCount++; }
/// <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 + "毫秒。"); } }
/// <summary> /// 初始化 /// </summary> /// <param name="client">初始化</param> public CommonStub(ISerClient client) { this.client = client; chanelType = Type.GetType(client.Owner.Config["ChanelType"]); realStub = client.GetStub(chanelType); }