客户端这边,如果每次都临时建立一个新的连接,那么连接的开销非常大。
业内常用的连接池组件是 Commons Pool2---版本 2.4.2
packageservice.pool;
importorg.apache.commons.pool2.BasePooledObjectFactory;
importorg.apache.commons.pool2.PooledObject;
importorg.apache.commons.pool2.impl.DefaultPooledObject;
importorg.apache.thrift.transport.TSocket;
publicclassMyPoolFactoryextendsBasePooledObjectFactory {
privateStringip;
privateintport;
publicMyPoolFactory(Stringstring,inti) {
ip=string;
port=i;
}
@Override
publicTSocket create()throwsException {
// 初始化一个对象
TSocketts=newTSocket(ip,port);
ts.open();
returnts;
}
@Override
publicPooledObject wrap(TSocketts) {
// 默认操作
returnnewDefaultPooledObject(ts);
}
/// 下面是5个生命周期
//makeObject默认
@Override
publicvoiddestroyObject(PooledObjectp)throwsException {
TSocketts=p.getObject();
ts.close();
}
@Override
publicbooleanvalidateObject(PooledObjectp) {
TSocketts=p.getObject();
returnts.isOpen();
通过发送紧急数据解决此问题,Thrift服务器端不要开启对应的设置,经过测试OK.
然后,后来又想到,我自己写一个MyTSocket 继承TSocket,然后一旦业务线程拿到连接池给我的一个MyTSocket(注意:此时可能socket无效)
然后业务线程使用过程中发现有异常,则设置MyTSocket的一个属性为false,连接池检测时兼顾这个属性就可以了。
最后发现这个还不能彻底解决问题,jedis采用的是业务探测:ping-pong,这个是redis自己的协议
对于其它的服务器怎么办?我们查了百度,采用的办法是:
publicbooleanvalidateObject(PooledObjectp) {
MyTSockett=p.getObject();
Sockets=t.getSocket();
booleanclosed=s.isClosed();
booleanconnected=s.isConnected();
booleanoutputShutdown=s.isOutputShutdown();
booleaninputShutdown=s.isInputShutdown();
booleanurgentFlag=false;
try{
s.sendUrgentData(0xFF); //在这里
}catch(IOExceptione) {
}
returnurgentFlag&&connected&& !closed&& !inputShutdown&& !outputShutdown&&t.isAlive();
}
}
@Override
publicvoidactivateObject(PooledObjectp)throwsException {
// 返回给调用方时,做一些额外的操作
}
/**
* When an object is returned to the pool, clear the buffer.
*/
@Override
publicvoidpassivateObject(PooledObjecttSocket) {
// 返回到pool时,做一些额外的操作
}
}
============================
具体使用时
// 设置传输通道,对于非阻塞服务,需要使用TFramedTransport,它将数据分块发送
GenericObjectPoolConfigpoolConfig=newGenericObjectPoolConfig();
poolConfig.setBlockWhenExhausted(true);
poolConfig.setMaxWaitMillis(100);
poolConfig.setLifo(false);
poolConfig.setMaxIdle(50); 最大空闲连接数
poolConfig.setMinIdle(50);// 最小空闲连接数
poolConfig.setMaxTotal(100);// 整个池的最大值,最大连接数
poolConfig.setTestOnBorrow(true);
poolConfig.setTestOnCreate(true);
poolConfig.setTestOnReturn(true);
poolConfig.setTestWhileIdle(false);
GenericObjectPoolpools=newGenericObjectPool(newMyPoolFactory("127.0.0.1", 7911),poolConfig);
// 具体使用代码
TSocketts= (TSocket)pools.borrowObject();
pools.returnObject(ts);