自定义Thrift连接池
来源:互联网 发布:上海租房网站 知乎 编辑:程序博客网 时间:2024/06/01 17:28
自定义Thrift连接池
Thrift作为一个高性能的RPC框架,广泛应用于后端服务的进程间接口调用场景中。对于Java开发者而言,thrift客户端调用框架并没有提供相关的连接池能力进行使用,对于性能要求较高的用户可以自定义Thrift连接池以满足自身的需求,本着不重复造轮子的原则,笔者使用apache commons-pools2实现了一套自定义的Thrift连接池供大家参考。
关于apache commons-pools2的相关知识,大家可以参考这篇博文:http://blog.csdn.net/amon1991/article/details/77110657
1、创建池对象工厂
PooledObjectFactory(池对象工厂)是commons-pools2中的一个概念,用于控制整个池对象的整个生命周期。
在我们的实例中,这个池对象就是TProtocol对象,准确来说,commons-pools2管理的对象其实是TProtocol在池中的封装对象,也就是实例中通过wrap(TProtocol protocol)方法包裹后生成的对象PooledObject,这个封装的对象保有实际被包装对象的复杂的状态信息,这个状态信息在判断对象是否存活,是否可以被销毁时起到了关键作用。下面给出实际的新建Thfift池对象工厂代码,笔者使用的是TMultiplexedProtocol对象,使用其他TProtocol对象的参考这种写法即可。
代码块
public class TProtocolFactory extends BasePooledObjectFactory<TProtocol>{ private final Logger logger = LoggerFactory.getLogger(this.getClass()); private static final int TIMEOUT = 3000000; // 超时时间 private static final int MAX_LENGTH = 1638400000; // 单次最大传输的数据量(1.6G) public static final String PI_SERVICE = "PiService"; public static final String OPC_SERVICE = "OpcService"; private String host; private int port; private boolean keepAlive = true; // 是否持有Thrift连接,不持有则钝化时释放连接 private String sourceType; // PI数据源还是OPC数据源 public TProtocolFactory(String host, int port, boolean keepAlive, String sourceType) { this.host = host; this.port = port; this.keepAlive = keepAlive; this.sourceType = sourceType; } private TProtocolFactory() { } /** * 创建新对象 * @return * @throws Exception */ @Override public TProtocol create() throws Exception { TSocket tSocket = new TSocket(host, port,TIMEOUT ); TTransport tTransport = new TFramedTransport(tSocket,MAX_LENGTH); if (null!= tTransport && !tTransport.isOpen()){ tTransport.open(); } TProtocol protocol = new TCompactProtocol(tTransport); if (null != sourceType) { if (sourceType.equals(PI_SERVICE)){ return new TMultiplexedProtocol(protocol,PI_SERVICE); }else if (sourceType.equals(OPC_SERVICE)){ return new TMultiplexedProtocol(protocol,OPC_SERVICE); }else { return null; } }else { return null; } } /** * 将对象放入对象池前先包装对象,好让对象池可以管理 * @param protocol * @return */ @Override public PooledObject<TProtocol> wrap(TProtocol protocol) { return new DefaultPooledObject<>(protocol); } /** * 对象钝化(即:从激活状态转入非激活状态,returnObject时触发) * @param pooledObject * @throws TTransportException */ @Override public void passivateObject(PooledObject<TProtocol> pooledObject) throws TTransportException { if (null!= pooledObject.getObject()){ if (!keepAlive) { pooledObject.getObject().getTransport().flush(); pooledObject.getObject().getTransport().close(); } } } /** * 对象激活(borrowObject时触发) * @param pooledObject * @throws TTransportException */ @Override public void activateObject(PooledObject<TProtocol> pooledObject) throws TTransportException { if (!pooledObject.getObject().getTransport().isOpen()) { pooledObject.getObject().getTransport().open(); } } /** * 对象销毁(clear时会触发) * @param pooledObject * @throws TTransportException */ @Override public void destroyObject(PooledObject<TProtocol> pooledObject) throws TTransportException { if (null!= pooledObject.getObject()){ if (pooledObject.getObject().getTransport().isOpen()) { pooledObject.getObject().getTransport().flush(); pooledObject.getObject().getTransport().close(); } } pooledObject.markAbandoned(); } /** * 验证对象的有效性 * @param pooledObject * @return */ @Override public boolean validateObject(PooledObject<TProtocol> pooledObject) { if (pooledObject.getObject() != null) { if (pooledObject.getObject().getTransport().isOpen()) { return true; } try { pooledObject.getObject().getTransport().open(); return true; } catch (TTransportException e) { logger.error(e.getMessage()); } } return false; }}
2、创建对象池实例
Object Pool(对象池)是实际管理所有池对象的容器,主要的方法是borrowObject、returnObject,一个是从池中获取对象,另一个是使用完对象后将对象归还到池中,当然,该容器还提供了一些基本的方法用于获取当前存活的对象数,空闲的对象数等信息,这些信息可用于自定义销毁对象策略等实现。
由于笔者的代码中用到了Spring框架,所以外部代码获取连接池实例使用的是Spring容器管理的单例实例。注意,在对象池的使用上,必须保证对象池是线程安全的,否则可能在多线程环境导致对象池维护的数据产生不一致的问题。假设没有使用Spring框架,笔者推介使用一个饿汉模式的单例来维护pool对象即可。
@Componentpublic class OPCTProtocolPool { @Autowired private PiDataSourceConf piDataSource; @Autowired private ObjectPoolConfig objectPoolConfig; private ObjectPool<TProtocol> pool; /** * 获取 thrift 连接对象池 * @return */ public ObjectPool<TProtocol> getPool() { if (pool == null){ GenericObjectPoolConfig poolConfig = objectPoolConfig.getGenericObjectPoolConfig(); // 第一次加载对象池 pool = new GenericObjectPool<>(new TProtocolFactory(piDataSource.getIp(), piDataSource.getPort(), true ,TProtocolFactory.OPC_SERVICE), poolConfig); } return pool; }}
以上代码中,GenericObjectPoolConfig 对象可以设置连接池的参数,比如最大连接数、最大空闲数、超时时间等信息,具体可以参考commons-pools中的通用配置即可。
3、使用对象池使用TProtocol对象
完成上面两步之后,就可以从对象池中非常简单的获取TProtocol对象了,获取对象使用如下代码:
TProtocol protocol = protocolPool.getPool().borrowObject();
使用完对象后,必须使用同一个对象池返回使用的对象,否则这个对象就在进程中失控了:
protocolPool.getPool().returnObject(protocol);
- 自定义Thrift连接池
- Thrift连接池实现
- thrift连接池问题
- Thrift连接池优化
- Thrift连接池实现
- 实现Thrift客户端连接池
- Thrift客户端连接池设计
- (转载) java thrift 连接池
- Thrift学习笔记(4)--实现Thrift客户端连接池
- thrift 异步连接池 创建 c++
- thrift 客户端 ,负载均衡 连接池
- Thrift之C++ 异步连接池实例
- ATC:go Thrift RPC 使用 (连接池)
- thrift的TTransport连接池注意事项[Java版本说明]
- Thrift连接池优化http://write.blog.csdn.net/mdeditor
- Thrift 池
- python利用thrift连接hive
- Ubuntu安装Thrift连接Hive
- 最长包含区间
- [Python/SaltStack] 运用Python语言进行自定义Salt模块
- Linux源码安装MySQL5.5.11
- Androidstudio重启后错误:Error:Unexpected lock protocol found in lock file. Expected 3, found 0.
- 单点登录详解(一)--使用Cookie+Filter实现单点登录
- 自定义Thrift连接池
- 简易安装nodejs和npm的方法
- python的动态类型简介
- hive 自定义函数
- OpenCV图像处理编程实例-勘误
- TensorFlow学习笔记(二十七)CNN的9大模型之Dan CiresanNet
- 如何实现双向链表的插入、删除操作
- Mysql5.5升级到5.6步骤详解
- Java实现基本的栈和队列