Apache Thrift 是 Facebook 实现的一种高效的、支持多种编程语言的远程服务调用的框架。具体的介绍可以看Apache的官方网站:/。今天并不介绍thrift如何使用,只是演示一下如何使用commons-pool2建立thrift连接池,这样可以快速访问服务端。
我演示的thrift接口如下所示:
public interface Iface {public String genNewKTVOrder(com.ethank.thrift.iface.service.TOrder torder) throws org.apache.thrift.TException;public String genWeiXinPreOrder(String orderId, String body) throws org.apache.thrift.TException;public String genPreKTVGoodsOrder(String reserveGoodsId, String reserveBoxId, String goodsList, String sumPrice, int userId, String ktvId) throws org.apache.thrift.TException;public String genWeiXinQRCode(String orderId, String body) throws org.apache.thrift.TException;}
这些代码都是通过thrift自动生成的,具体如何操作可以看网上搜索一些thrift教程。
thrift客户端是这样一个内部类:
public static class Client extends org.apache.thrift.TServiceClient implements Iface
我的思路实在pool中放入org.apache.thrift.transport.TSocket对象,其工厂方法如下:
import mons.pool2.BasePooledObjectFactory;import mons.pool2.PooledObject;import mons.pool2.impl.DefaultPooledObject;import org.apache.thrift.transport.TSocket;public class ConnectionFactory extends BasePooledObjectFactory<TSocket>{@Overridepublic TSocket create() throws Exception {TSocket transport = new TSocket("192.168.1.222", 34568, 2000); //建立TSocket,根据具体情况可以修改transport.open();return transport;}@Overridepublic boolean validateObject(mons.pool2.PooledObject<TSocket> p){ //校验对象有效性TSocket transport = p.getObject();return transport.isOpen();}@Overridepublic PooledObject<TSocket> wrap(TSocket obj) { //创建包装对象,包装对象是真正放在pool中的对象return new DefaultPooledObject<TSocket>(obj);}@Overridepublic void destroyObject(PooledObject<TSocket> p) throws Exception { //销毁对象,关闭链接if (p.getObject().isOpen()) {p.getObject().close();}}}
实际调用中并不是用的TSocket,而是Client对象,为此建立ConnectionManager利用TSocket建立Client对象:
import mons.pool2.impl.GenericObjectPool;import mons.pool2.impl.GenericObjectPoolConfig;import org.apache.thrift.protocol.TCompactProtocol;import org.apache.thrift.protocol.TProtocol;import org.apache.thrift.transport.TSocket;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import com.ethank.thrift.iface.service.EthankOrderService;public class ConnectionManager {private static final Logger LGR = LoggerFactory.getLogger(ConnectionManager.class);private static GenericObjectPool<TSocket> pool;static {ConnectionFactory connectionFactory = new ConnectionFactory();GenericObjectPoolConfig config = new GenericObjectPoolConfig();config.setMaxIdle(10); //最大空闲数量config.setMaxTotal(20); //连接池最大数量config.setMinIdle(3); //最小空闲数量config.setTestOnBorrow(true); //在从pool中去对象时进行有效性检查,会调用工厂中的validateObjectconfig.setMaxWaitMillis(1000); //提取对象时最大等待时间,超时会抛出异常config.setMinEvictableIdleTimeMillis(60000); // 最小的空闲对象驱除时间间隔,空闲超过指定的时间的对象,会被清除掉config.setTimeBetweenEvictionRunsMillis(30000);//后台驱逐线程休眠时间config.setNumTestsPerEvictionRun(3); //设置驱逐线程每次检测对象的数量config.setTestWhileIdle(true); //是否对空闲对象使用PoolableObjectFactory的validateObject校验,pool = new GenericObjectPool<TSocket>(connectionFactory, config);} public static EthankOrderService.Client getThriftConnetion(){TSocket socket;try {socket = pool.borrowObject();TProtocol protocol = new TCompactProtocol(socket);EthankOrderService.Client client= new EthankOrderService.Client(protocol);client.socket = socket;return client;} catch (Exception e) {e.printStackTrace();}return null;}public static void returnThriftConnetion(EthankOrderService.Client client){pool.returnObject(client.socket);}public static int getPoolObjectNum() {return pool.getNumIdle();}}
测试类做测试:
public static void main(String[] args) {for (int i = 0; i < 20; i++) {try {new Thread(new Runnable() {public void run() {EthankOrderService.Client client = null;try {client = ConnectionManager.getThriftConnetion();String re = client.genWeiXinPreOrder("1111111", "222");System.out.println(re+" "+ client.socket.hashCode());} catch (Exception e) {e.printStackTrace();}finally{ConnectionManager.returnThriftConnetion(client);}}}).start();} catch (Exception e) {e.printStackTrace();}}
}
这只是一个最简单的pool使用实例,可以做很多的改进,如优化pool中对象,加入动态代理以屏蔽client其他接口。此实例尽起抛砖引玉!
参考资料:
1. apache commons-pool的配置参数 /group/topic/96620/