thrift - C#(CSharp)客户端连接池(ConnectionPool)
var tran = ThriftPool.Instance().BorrowInstance();
TProtocol protocol = new TBinaryProtocol(tran);
var client = new xxxx(protocol); //xxxx为生成的thrift代理类的Client对象
var ret = client.TestMethod(parameters); //TestMethod为业务方法名称
ThriftPool.Instance().ReturnInstance(tran);
return ret;
internal class ThriftConfig
{
#region 单例入口 private static ThriftConfig instance = null;
private static object objLock = new object();
public static ThriftConfig Instance()
{
if (instance == null)
{
lock (objLock)
{
if (instance == null)
{
instance = new ThriftConfig();
}
}
}
return instance;
} #endregion #region 私有构造函数 private ThriftConfig()
{
Host = ConfigHelper.GetAppSettingValue("ESHost");
Port = ConfigHelper.GetAppSettingInt32Value("ESPort");
Encode = Encoding.UTF8;
Timeout = 3000;
MaxActive = ConfigHelper.GetAppSettingInt32Value("ESMaxActiveConnectionCount");
MaxIdle = ConfigHelper.GetAppSettingInt32Value("ESMaxIdleConnectionCount");
MinIdle = ConfigHelper.GetAppSettingInt32Value("ESMinIdleConnectionCount");
MaxWait = 5;
} #endregion #region 配置属性定义 public string Host { get; set; } public int Port { get; set; } public Encoding Encode { get; set; } public bool Zipped { get; set; } public int Timeout { get; set; } public int MaxActive { get; set; } public int MaxIdle { get; set; } public int MinIdle { get; set; } public int MaxWait { get; set; }
#endregion }
internal class ThriftPool
{
#region 属性 private ThriftConfig config; /// 对象缓存池
private static Stack<TTransport> objectPool { get; set; }
/// 同步对象
private static AutoResetEvent resetEvent; /// 空闲对象数
private static volatile int idleCount = 0; private static volatile int activeCount = 0; /// 同步对象锁
private static object locker = new object(); #endregion #region 单例入口 private static long testcount = 0;
private static ThriftPool instance = null;
private static object objLock = new object();
public static ThriftPool Instance()
{
if (instance == null)
{
lock (objLock)
{
if (instance == null)
{
instance = new ThriftPool();
}
}
}
return instance;
} #endregion #region 构造函数 private ThriftPool()
{
config = ThriftConfig.Instance();
CreateResetEvent();
CreateThriftPool();
} #endregion #region 公有操作方法 /// 从对象池取出一个对象
public TTransport BorrowInstance()
{
lock (locker)
{
//Zkx.Infrastruction.Logger.Log.DebugFormat("借前对象池个数:{0},空闲个数:{1}", objectPool.Count(), idleCount);
TTransport transport;
//对象池无空闲对象 if (idleCount == 0)
{
//对象池已已创建对象数达上限
if (activeCount >= config.MaxActive)
{
//Console.WriteLine("waiting..." + activeCount);
resetEvent.WaitOne();
}
else
{
PushObject(CreateInstance());
}
}
transport = objectPool.Pop();
//Console.WriteLine("Pop 对象..." + transport.IsOpen); //空闲对象数小于最小空闲数,添加一个对象到对象池(已创建数不能超标)
if (--idleCount < config.MinIdle && activeCount < config.MaxActive)
{
PushObject(CreateInstance());
} ValidateInstance(transport);
//Console.WriteLine("借出......对象池个数:{0},空闲个数:{1}," + testcount, objectPool.Count(), idleCount);
return transport;
}
} /// 归还一个对象
/// <param name="instance"></param>
public void ReturnInstance(TTransport instance)
{
lock (locker)
{
// Console.WriteLine("Push 对象..." + instance.IsOpen); //空闲对象数达到上限,不再返回线程池,直接销毁
if (idleCount == config.MaxIdle)
{
DestoryInstance(instance);
}
else
{
ValidateInstance(instance);
PushObject(instance);
//发通知信号,有对象归还到对象池
resetEvent.Set();
//Console.WriteLine("归还...");
}
}
}
#endregion #region 私有方法 /// 创建线程同步对象
private void CreateResetEvent()
{
lock (locker)
{
if (resetEvent == null)
{
resetEvent = new AutoResetEvent(false);
}
}
} /// 创建对象池
private void CreateThriftPool()
{
lock (locker)
{
if (objectPool == null)
{
objectPool = new Stack<TTransport>();
}
}
} /// 添加对象到对象池
private void PushObject(TTransport transport)
{
objectPool.Push(transport);
idleCount++;
} /// 创建一个对象
private TTransport CreateInstance()
{
activeCount++;
var objsocket = new TSocket(config.Host, config.Port);
objsocket.Timeout = 5000;
TTransport transport = objsocket; transport.Open();
//Console.WriteLine("创建对象..." + activeCount);
return transport;
} /// 校验对象
private void ValidateInstance(TTransport instance)
{
if (!instance.IsOpen)
{
//Console.WriteLine("校验_重新打开...");
instance.Open();
}
} /// 销毁对象
private void DestoryInstance(TTransport instance)
{
if (instance.IsOpen)
{
instance.Close();
}
//instance.Flush();
instance.Dispose();
activeCount--;
//Console.WriteLine("销毁...");
} #endregion
}
thrift - C#(CSharp)客户端连接池(ConnectionPool)的更多相关文章
- 由浅入深了解Thrift之客户端连接池化续
前文<由浅入深了解Thrift之客户端连接池化>中我们已经实现了服务调用端 连接的池化,实现的过于简陋,离实际的项目运用还很遥远.本文将在进一步改造,主要是两方面:1.服务端如何注册多个服 ...
- Redis客户端连接池
使用场景 对于一些大对象,或者初始化过程较长的可复用的对象,我们如果每次都new对象出来,那么意味着会耗费大量的时间. 我们可以将这些对象缓存起来,当接口调用完毕后,不是销毁对象,当下次使用的时候,直 ...
- 由浅入深了解Thrift之客户端连接池化
一.问题描述 在上一篇<由浅入深了解Thrift之服务模型和序列化机制>文章中,我们已经了解了thrift的基本架构和网络服务模型的优缺点.如今的互联网圈中,RPC服务化的思想如火如荼.我 ...
- Swoole2.0协程客户端连接池的实现
Swoole2.0官方默认的实例是短连接的,在请求处理完毕后就会切断redis或mysql的连接.实际项目可以使用连接池实现复用. 实现原理也很简单,使用SplQueue,在请求到来时判断资源队列中是 ...
- redis客户端连接异常
本文参考:http://mdba.cn/2015/04/02/redistwemproxy-%e5%ae%a2%e6%88%b7%e7%ab%af%e8%bf%9e%e6%8e%a5%e5%bc%82 ...
- [20171106]配置客户端连接注意.txt
[20171106]配置客户端连接注意.txt --//在配置客户端连接时一般建议使用Net Manager工具,windows下调用执行Net Manager.--//linux下执行 netmgr ...
- QTcpServer实现多客户端连接
版权声明:若无来源注明,Techie亮博客文章均为原创. 转载请以链接形式标明本文标题和地址: 本文标题:QTcpServer实现多客户端连接 本文地址:https://www.techiel ...
- 一个I/O线程可以并发处理N个客户端连接和读写操作 I/O复用模型 基于Buf操作NIO可以读取任意位置的数据 Channel中读取数据到Buffer中或将数据 Buffer 中写入到 Channel 事件驱动消息通知观察者模式
Tomcat那些事儿 https://mp.weixin.qq.com/s?__biz=MzI3MTEwODc5Ng==&mid=2650860016&idx=2&sn=549 ...
- 高版本->低版本迁移,低版本客户端连接高版本数据库EXP导出报错EXP-00008,ORA-01455,EXP-00000
生产环境: 源数据库:RHEL + Oracle 11.2.0.3 目标数据库:HP-UX + Oracle 10.2.0.4 需求:迁移部分表 11.2.0.3-->10.2.0.4,若 ...
随机推荐
- Programming Recipes
Recipes是从一本书上看来的,即有诀窍又有食谱的意思.这里想记一些工作中遇到的问题和解决方法,说决窍有点过了,说食谱照单做又不足,所以Recipe这个词两个意思都有混合起来正合适. 1.Windo ...
- 使用序列号激活优动漫PAINT(附激活码)
优动漫PAINT是一款功能强大的动漫绘图软件,简单的中文界面和丰富的笔刷操纵,再次为设计工作者带来非一般的感受!最近,有不少小伙伴提出这样的疑问:购买安装优动漫PAINT之后,不知道如何激活,在哪里输 ...
- location.reload() 和 location.replace()的区别和应用。
首先介绍两个方法的语法: reload 方法,该方法强迫浏览器刷新当前页面.语法:location.reload([bForceGet]) 参数:bForceGet, 可选参数, 默认为 false ...
- navicat Premium远程链接mysql报错
1,报错1057,原来是没有远程权限连接mysql 2.打开my.ini文件,添加skip-grant-tables跳过验证 3.添加到path环境变量,前面是英文下的分号 4.切换到cmd,输入my ...
- Guava 是个风火轮之基础工具 (1)
转自:http://www.jamespan.me/blog/2015/02/08/guava-basic-utilities-1/ Guava 是个风火轮之基础工具 (1) 前言 Guava 是 J ...
- CentOS6.8安装
VMware下CentOS 6.8安装配置 简述 Linux的安装方法有很多种,下面,我们主要以镜像安装为例,介绍CentOS的安装过程及相关的参数设置,详细步骤如下. CentOS安装配置 ...
- Problem 13
Problem 13 # Problem_13 """ Work out the first ten digits of the sum of the following ...
- 导出MNIST的数据集
在TensorFlow的官方入门课程中,多次用到mnist数据集. mnist数据集是一个数字手写体图片库,但它的存储格式并非常见的图片格式,所有的图片都集中保存在四个扩展名为idx3-ubyte的二 ...
- 【codeforces 799A】Carrot Cakes
[题目链接]:http://codeforces.com/contest/799/problem/A [题意] 你有一个烤炉; 每t秒能同时烤出k个蛋糕; 你可以在第一个烤炉在烤的时候;同时花费d秒建 ...
- HDU——T1231 最大连续子序列
http://acm.hdu.edu.cn/showproblem.php?pid=1231 Problem Description 给定K个整数的序列{ N1, N2, ..., NK },其任意连 ...